windows网络通讯:1、网络常识;2、socket;3、tcp通信;4、udp通信
网络架构:七层,五层架构(基于功能或者协议来划分)
7层:应用层,表示层,会话层,传输层,网络层,数据链路层,物理层
5层:应用层(应用层,表示层,会话层),传输层,网络层,数据链路层,物理层
tcp/ip是一个协议族
socket ip地址,端口号(源ip地址与目标地址ip以及源端口号和目标端口号的组合称为套接字)
tcp通信 建立稳定连接
服务端代码:
//c/s模型(一对一)
//1、准备工作,导头文件
//2、确定版本信息,确定socket版本,ipv4和ipv6版本,win32编程使用ipv4版本
//3、创建socket
//4、初始化协议地址族
//5、绑定(把协议地址族和socket绑定在一起)(注意:客户端不需要绑定)
//6、监听(客户端不需要监听)
//7、服务端:接受监听;客户端:连接
//8、开始通讯
//9、关闭socket
//1、准备工作,导头文件
#include<WinSock2.h>
#include<stdlib.h>
#pragma comment(lib,"ws2_32.lib")
int _tmain(int argc, _TCHAR *argv[])
{
//2、确定版本信息
WSADATA wsaData;
//第1个参数是版本请求,请求哪个版本,高阶字节指的是修订版本,低阶字节指的是主版本号
//第二个参数是一个结构体,用来接收socket实现的细节
WSAStartup(MAKEWORD(2, 2), &wsaData);//异步实现套接字的启动命令
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
{
printf("请求版本失败,启动不成功\n");
getchar();
return -1;
}
printf("请求版本成功\n");
//3、创建socket
//第1个参数协议族,表示当前socket要用什么类型的地址和端口
//AF_INET表示要用ipv4的地址(32位)与端口号(16位)的组合
//
SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == serverSocket)
{
printf("套接字创建失败\n");
WSACleanup();//关闭套接字请求
system("pause");
return -1;
}
printf("套接字创建成功\n");
//4、初始化协议地址族
SOCKADDR_IN serverAddr = { 0 };//初始化一下协议地址
serverAddr.sin_family = AF_INET;//必须和第3步创建socket时的参数一致
//端口号需要存储,需要注意:网络的数值和pc的存储数值是有区别的,pc是先存低位再存高位(小端)
// 在网络是(大端)先是高位再是低位,把pc的数值转为网络htons来转换
serverAddr.sin_port = htons(8888);//这是服务端的端口,客户端要通过这个端口才能连接
//ip地址的表示是点分格式的字符串,用inet_addr来转换为整数
serverAddr.sin_addr.S_un.S_addr = inet_addr("10.214.74.106/15");
//5、绑定
//第2个参数为协议地址族的首地址
if (SOCKET_ERROR == bind(serverSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)))
{
printf("绑定失败\n");
closesocket(serverSocket);//释放socket
WSACleanup();//关闭套接字请求
getchar();
return -1;
}
printf("绑定成功\n");
//6、监听
//第2个参数是监听的个数。是等待连接的队列的最大长度
if (SOCKET_ERROR == listen(serverSocket, 10))
{
printf("监听失败\n");
closesocket(serverSocket);
WSACleanup();
getchar();
return -1;
}
printf("监听成功\n");
//7、接受连接
//第2个参数和第3个参数可以
SOCKADDR_IN clientAddr = { 0 };
int len = sizeof(clientAddr);
SOCKET clientSocket = accept(serverSocket, (sockaddr*)&clientAddr,&len);
if (clientSocket == INVALID_SOCKET)
{
printf("连接失败\n");
closesocket(serverSocket);
WSACleanup();
return -1;
}
printf("连接失败\n");
printf("有客户连接进来,客户端的ip:%s\n", inet_ntoa(clientAddr.sin_addr));
//8、开始通讯
char buff[128] = {};
while (1)
{
memset(buff, 0, sizeof(buff));
//第一个参数代表客户端socket,表示客户端进行接收数据
//第4个参数表示接收方式,0表示默认方式,一次收完
if (recv(clientSocket, buff, sizeof(buff)-1, 0) > 0)//阻塞函数
{
printf(">>:%s\n", buff);
}
char clientbuff[128] = {};
memset(clientbuff, 0, sizeof(clientbuff));
printf("请输入:");
scanf_s("%s", clientbuff, sizeof(clientbuff)-1);
send(clientSocket, clientbuff, strlen(clientbuff), 0);
}
//9、关闭socket
closesocket(clientSocket);
closesocket(serverSocket);
WSACleanup();
system("pause");
return 0;
}
客户端代码:
#include "stdafx.h"
//开始准备工作,导头文件
#include<WinSock2.h>
#pragma comment(lib,"ws2_32.lib")
#define _WINSOCK_DEPRECATED_NO_WARNINGS
int _tmain(int argc, _TCHAR* argv[])
{
//2、确定版本信息
WSADATA wsaData;
//第1个参数是版本请求,请求哪个版本,高阶字节指的是修订版本,低阶字节指的是主版本号
//第2个参数是一个结构体,用来接收socket实现的细节
WSAStartup(MAKEWORD(2, 2), &wsaData);//异步套接字的启动命令
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
{
printf("请求版本失败,启动不成功\n");
return -1;
}
printf("请求版本成功\n");
//3、创建socket
//第1个参数协议族,表示当前socket要用什么类型的地址和端口
//第2个参数表示类型,SOCK_STREAM表示流式socket,面向连接socket
//第3个参数指定协议 IPPROTO_TCP 表示tcp传输协议
//返回一个socket
SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == clientSocket)
{
printf("套接字创建失败\n");
WSACleanup();//关闭套接字请求
return -1;
}
printf("套接字创建成功\n");
//4、初始化协议地址族(初始化的是给服务端ip地址及端口)
SOCKADDR_IN clientAddr = { 0 };//初始化一下协议地址
clientAddr.sin_family = AF_INET;//必须和第3步创建socket时参数一致
//端口号需要存储,需要注意:网络的数值和pc的存储数值是有区别的,pc是先存低位,再存高位(小端)
//在网络是(大端)先是高位再是低位,把pc的数值转化为网络htons来转换
clientAddr.sin_port = htons(8888);//这是服务的端口,客户端通过这个端口才能连接
//ip地址的表示是点分格式的字符串,用inet_addr来转换为整数
clientAddr.sin_addr.S_un.S_addr = inet_addr("10.214.74.106/15");
//5、连接
if (SOCKET_ERROR == connect(clientSocket, (sockaddr*)&clientAddr, sizeof(clientAddr)))
{
printf("连接失败\n");
closesocket(clientSocket);//释放socket
WSACleanup();//关闭套接字请求
return -1;
}
printf("连接不成功\n");
//开始通讯
char buff[128] = {};
while (1)
{
memset(buff, 0, sizeof(buff));
printf("请输入:");
scanf_s("%s", buff, sizeof(buff)-1);
send(clientSocket, buff, strlen(buff), 0);//send发消息是发给clientSocket所指的ip和端口
char mm[128] = {};
if (recv(clientSocket, mm, sizeof(mm)-1, 0) > 0);//阻塞函数
{
printf(">>:%s\n", mm);
}
}
//关闭socket
closesocket(clientSocket);
WSACleanup();//关闭套接字请求
getchar();
return 0;
}