WinSocket编程笔记(五)
三.UDP的Socket编程
先前的socket服务器端与客户端需要建立连接才能通信,因此是面向连接的基于TCP的Socket。而这里的基于UDP的Socket是面向无连接的,也就是说不必调用 listen() 和 accept() 函数,那么connect()函数也就一样没有使用的必要了。
UDP新增的函数:
1.发送数据sendto() 函数(相比send()函数多了最后面两个参数)
函数原型:
int sendto(int s, const void * buf, int len, unsigned int flags, const struct sockaddr * to, int addrlen);
- sock:用于传输UDP数据的套接字;
- buf:保存待传输数据的缓冲区地址;
- len:带传输数据的长度(以字节计);
- flags:可选项参数,若没有可传递0;
- to:存有目标地址信息的 sockaddr 结构体变量的地址;
- addrlen:传递给参数 to 的地址值结构体变量的长度;
定义实例:
sendto(sock, buffer, strlen(buffer), 0, (struct sockaddr*)&servAddr, sizeof(servAddr));
2.接收数据recvfrom() 函数
函数原型:
int recvfrom(SOCKET sock, char *buf, int nbytes, int flags, const struct sockaddr *from, int *addrlen);
- sock:用于接收UDP数据的套接字;
- buf:保存接收数据的缓冲区地址;
- nbytes:可接收的最大字节数(不能超过buf缓冲区的大小);
- flags:可选项参数,若没有可传递0;
- from:存有发送端地址信息的sockaddr结构体变量的地址;
- addrlen:保存参数 from 的结构体变量长度的变量地址值;
定义实例:
recvfrom(sock, buffer, BUF_SIZE, 0, &clntAddr, &nSize);
基于UDP的Socket编程
服务器:
#include <cstdio> #include<iostream> #include<string> #include<WinSock2.h> #pragma comment(lib,"ws2_32.lib") using namespace std; const int PORT = 8000; #define BUF_SIZE 100 int main(){ WORD sockVersion = MAKEWORD(2, 2); WSADATA data; if (WSAStartup(sockVersion, &data) != 0) { return 1; } SOCKET ListenSocket = socket(AF_INET,SOCK_STREAM,0); SOCKADDR_IN ListenAddr; ListenAddr.sin_family=AF_INET; ListenAddr.sin_addr.S_un.S_addr=INADDR_ANY; ListenAddr.sin_port=htons(PORT); int n; n=bind(ListenSocket,(LPSOCKADDR)&ListenAddr,sizeof(ListenAddr)); if(n==SOCKET_ERROR){ cout<<"端口绑定失败!"<<endl; return -1; } else{ cout<<"端口绑定成功:"<<PORT<<endl; } //接收客户端 SOCKADDR clntAddr; //客户端地址信息 int nSize = sizeof(SOCKADDR); char buffer[BUF_SIZE]; //缓冲区 while(1){ int strLen = recvfrom(ListenSocket, buffer, BUF_SIZE, 0, &clntAddr, &nSize); sendto(ListenSocket, buffer, strLen, 0, &clntAddr, nSize); } closesocket(ListenSocket); WSACleanup(); return(0); }
客户端:
#include <cstdio> #include<iostream> #include<string> #include<WinSock2.h> #pragma comment(lib,"ws2_32.lib") using namespace std; const int PORT = 8001; #define BUF_SIZE 100 int main(){ WORD sockVersion = MAKEWORD(2, 2); WSADATA data; if (WSAStartup(sockVersion, &data) != 0) { return 1; } SOCKET ListenSocket = socket(AF_INET,SOCK_STREAM,0); SOCKADDR_IN ListenAddr; ListenAddr.sin_family=AF_INET; ListenAddr.sin_addr.S_un.S_addr=INADDR_ANY; ListenAddr.sin_port=htons(PORT); int n; n=bind(ListenSocket,(LPSOCKADDR)&ListenAddr,sizeof(ListenAddr)); if(n==SOCKET_ERROR){ cout<<"端口绑定失败!"<<endl; return -1; } else{ cout<<"端口绑定成功:"<<PORT<<endl; } //服务器地址信息 sockaddr_in servAddr; memset(&servAddr, 0, sizeof(servAddr)); //每个字节都用0填充,可省略 servAddr.sin_family = PF_INET; servAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); servAddr.sin_port = htons(1234); //不断获取用户输入并发送给服务器,然后接受服务器数据 sockaddr fromAddr; int addrLen = sizeof(fromAddr); while(1){ char buffer[BUF_SIZE] = {0}; printf("Input a string: "); gets(buffer); sendto(ListenSocket, buffer, strlen(buffer), 0, (struct sockaddr*)&servAddr, sizeof(servAddr)); recvfrom(ListenSocket, buffer, BUF_SIZE, 0, &fromAddr, &addrLen); cout<<"Message from server:"<<buffer<<endl; } closesocket(ListenSocket); WSACleanup(); return(0); }
服务器端接收到客户端信息以后发回给客户端,客户端打印接收到的消息
运行结果
(待续)
[Sign]做不出ctf题的时候很痛苦,你只能眼睁睁看着其他人领先你