基于 UDP 无连接的 socket 编程
一、服务器端操作流程
1.1加载套接字库(WSAStartup)
1.2 创建套接字 (socket)
1.3将创建的套接字绑定到一个本地地址和端口上 (bind)
1.4等待接收数据。后与客户端实现实时交流 (recvfrom / sendto)
1.5关闭套接字
recvfrom函数将接收一个数据报信息并保存源地址。函数原型如下:
int recvfrom(SOCKET s, char FAR* buf, int len, int flags,struct sockaddr FAR* from, int FAR* fromlen);
a) s:准备接收数据的套接字。
b) buf:指向缓冲区的指针,该缓冲区用来接收数据。
c) len:缓冲区的长度。
d) flags:收发数据方式的标识,如果不需要特殊要求可以设置为0。
e) from:指向地址的结构体指针,用来接收发送数据方的地址信息。
f) fromlen:地址结构的大小。
sendto函数将向一个特定的目的方放松数据。其函数原型如下:
int sendto(SOCKET s, const char FAR* buf, int len, int flags,const struct sockaddr FAR* to, int tolen);
参数:
a)s:是一个(可能已建立连接的)套接字描述符。
b) buf:指向缓冲区的指针,该缓冲区包含将要发送的数据。
c) len:指定缓冲区中的数据长度。
d) flags:收发数据方式的标识,如果不需要特殊要求可以设置为0。
n to:该指针指向目标套接字的地址;
e) tolen:指定的地址长度
二、服务器端实例(UDP)
1 #include "stdafx.h" 2 #include <winsock2.h> 3 #include<iostream> 4 #pragma comment(lib,"ws2_32.lib") 5 using namespace std; 6 int main() 7 { 8 WORD wVersion; 9 WSADATA wsaData; 10 int er; 11 //1.初始化版本信息 12 wVersion = MAKEWORD(1, 1); 13 //加载套接字库 14 er = WSAStartup(wVersion, &wsaData); 15 if (er != 0) 16 { 17 return -1; 18 } 19 //检测套接字版本信息 20 if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) 21 { 22 WSACleanup(); 23 return -2; 24 } 25 26 //2.创建服务器端套接字 27 SOCKET sockSer = socket(AF_INET, SOCK_DGRAM, 0); 28 SOCKADDR_IN addr_in; 29 addr_in.sin_family = AF_INET;//地址族 30 addr_in.sin_port = htons(7000);//端口 31 addr_in.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//IP 32 bind(sockSer, (sockaddr*)&addr_in, sizeof(addr_in)); 33 34 SOCKADDR_IN client_addr; 35 int len = sizeof(sockaddr_in); 36 char recvBuf[1024]; 37 recvfrom(sockSer, recvBuf, sizeof(recvBuf), 0,(sockaddr*)&client_addr,&len); 38 cout << "接受到的数据:" << recvBuf << endl; 39 //向客户端发送数据 40 sendto(sockSer, recvBuf, sizeof(recvBuf), 0, (sockaddr*)&client_addr, len); 41 closesocket(); 42 WSACleanup(); 43 system("pause"); 44 return 0; 45 }
三、客户端操作流程
3.1加载套接字库 (WSAStartup)
3.2创建套接字 (socket)
3.3向服务器发送数据。后与服务端实现实时交流 (recvfrom / sendto)
3.4关闭套接字 (closesocket)
四、客户端实例(UDP)
1 #include "stdafx.h" 2 #include <winsock2.h> 3 #include<iostream> 4 #pragma comment(lib,"ws2_32.lib") 5 using namespace std; 6 int main() 7 { 8 WORD wVersion; 9 WSADATA wsaData; 10 int er; 11 //1.初始化版本信息 12 wVersion = MAKEWORD(1, 1); 13 //加载套接字库 14 er = WSAStartup(wVersion, &wsaData); 15 if (er != 0) 16 { 17 return -1; 18 } 19 //检测套接字版本信息 20 if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) 21 { 22 WSACleanup(); 23 return -2; 24 } 25 26 //2.创建服务器端套接字 27 SOCKET sockSer = socket(AF_INET, SOCK_DGRAM, 0); 28 SOCKADDR_IN addr_in; 29 addr_in.sin_family = AF_INET;//地址族 30 addr_in.sin_port = htons(7000);//端口 31 addr_in.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); 32 bind(sockSer, (sockaddr*)&addr_in, sizeof(addr_in)); 33 34 SOCKADDR_IN addr; 35 int len = sizeof(addr); 36 37 //向服务器发送数据 38 char sendBuf[1024]; 39 sendto(sockSer, sendBuf, sizeof(sendBuf), 0, (sockaddr*)&addr, len); 40 //接受数据 41 char recvBuf[1024]; 42 recvfrom(sockSer, recvBuf, sizeof(recvBuf), 0, (sockaddr*)&addr, &len); 43 cout << "接受到服务器端的数据:" << recvBuf << endl; 44 closesocket(); 45 WSACleanup(); 46 system("pause"); 47 return 0; 48 }
五、UDP工作原理图