UDP套接字
注意在UDP套接字中,要使用recvfrom和sendto
-
API:
-
recvfrom:
接收数据包,并存储源地址(UDP)
-
函数原型:
int WSAAPI recvfrom( [in] SOCKET s, [out] char *buf, [in] int len, [in] int flags, [out] sockaddr *from, [in, out, optional] int *fromlen );
-
参数:
- s:标识绑定套接字的描述符
- buf:传入数据的缓冲区
- len:缓冲区长度
- flags:用于修改函数调用行为
- from:指向sockaddr结构的指针,该缓冲区中将保留源地址
- fromlen:from指向的缓冲区大小
-
返回值:
如果未发生错误,recvfrom函数将返回收到的字节数
-
-
UDP Server:
#define _WINSOCK_DEPRECATED_NO_WARNINGS #include <iostream> #include <WinSock2.h> #pragma comment(lib,"ws2_32.lib") int main() { WORD wVersionRequested = MAKEWORD(2, 2); WSAData lpWSAData; if (WSAStartup(wVersionRequested, &lpWSAData)) { std::cout << "WSAStartup Error!" << std::endl; return -1; } //SOCKADDR_IN结构用于指定AF_INET地址系列的传输地址和端口 sockaddr_in saddr; saddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); saddr.sin_family = AF_INET; saddr.sin_port = htons(50123); SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) { return -1; } char opt; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); int nRet = bind(sock, (sockaddr*)&saddr, sizeof(saddr)); sockaddr_in raddr; int nLength = sizeof(sockaddr); char szReadBuffer[50]{ 0 }; while (true) { nRet = recvfrom(sock, szReadBuffer, 50, 0, (sockaddr*)&raddr, &nLength); if (nRet < 0) { return -1; } std::cout << "data:" << szReadBuffer << std::endl; std::cout << "请输入:"; char szBuffer[50]{ 0 }; std::cin >> szBuffer; sendto(sock, szBuffer, strlen(szBuffer), 0, (sockaddr*)&raddr, sizeof(sockaddr)); } WSACleanup(); system("pause"); return 0; }
-
UDP Client:
#define _WINSOCK_DEPRECATED_NO_WARNINGS #include <iostream> #include <WinSock2.h> #pragma comment(lib,"ws2_32.lib") int main() { WORD wVersionRequested = MAKEWORD(2, 2); WSAData lpWSAData; WSAStartup(wVersionRequested, &lpWSAData); sockaddr_in saddr; saddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); saddr.sin_family = AF_INET; saddr.sin_port = htons(50123); SOCKET SocClient = socket(AF_INET, SOCK_DGRAM, 0); if (SocClient < 0) { return -1; } char opt; setsockopt(SocClient, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); char szSendBuffer[50]{ 0 }; char szReadBuffer[50]{ 0 }; sockaddr_in raddr; int nLength = sizeof(raddr); while (true) { std::cout << "请输入:"; std::cin >> szSendBuffer; sendto(SocClient, szSendBuffer, strlen(szSendBuffer), 0, (sockaddr*)&saddr, sizeof(sockaddr)); recvfrom(SocClient, szReadBuffer, 50, 0, (sockaddr*)&raddr, &nLength); std::cout << "Server:" << szReadBuffer << std::endl; } closesocket(SocClient); WSACleanup(); system("pause"); return 0; }
原始套接字
- 服务端:
#define _WINSOCK_DEPRECATED_NO_WARNINGS #include <iostream> #include <WinSock2.h> #pragma comment(lib,"ws2_32.lib") typedef struct _IP_HEADER { //版本信息,首部长度 char cVersionAndHeaderLen; //服务类型 char vTypeOfServer; //数据包长度 short sTotalLenOfPacket; //数据包ID short sPacketID; //分片信息 short sSliceinfp; //生存时间 char cTTL; //协议类型 char cTypeOfProtocol; //首部校验和 short sCheckSum; //源IP地址 unsigned int uiSrcIP; //目的IP地址 unsigned int uiDestIP; }IP_HEADER, *pIP_HEADER; typedef struct _UDP_HEADER { //源端口号 unsigned short usSourPort; //目的端口号 unsigned short usDestIPPort; //数据包长度 unsigned short usLength; //校验和 unsigned short usCheckSum; }UDP_HEADER, pUDP_HEADER; int main() { WORD wVersionRequested = MAKEWORD(2, 2); WSAData lpWSAData; WSAStartup(wVersionRequested, &lpWSAData); sockaddr_in SAddr; SAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); SAddr.sin_family = AF_INET; SAddr.sin_port = htons(50123); SOCKET SocSrv = socket(AF_INET, SOCK_RAW, IPPROTO_UDP); if (SocSrv < 0) { return -1; } char opt; setsockopt(SocSrv, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); int nRet = bind(SocSrv, (sockaddr*)&SAddr, sizeof(SAddr)); if (nRet < 0) { return -1; } char szReadBuffer[500]{ 0 }; sockaddr_in raddr; int nLength = sizeof(sockaddr); while (true) { std::cout << "waiting......" << std::endl; nRet = recvfrom(SocSrv, szReadBuffer, 500, 0, (sockaddr*)&raddr, &nLength); IP_HEADER iph; UDP_HEADER udph; memcpy(&iph, szReadBuffer, 20); memcpy(&udph, szReadBuffer + 20, 8); int srcp = ntohs(udph.usSourPort); in_addr ias, iad; ias.s_addr = iph.uiSrcIP; iad.s_addr = iph.uiDestIP; char Temp[0x100]{ 0 }; strcpy_s(Temp, inet_ntoa(iad)); std::cout << "SrcIP:" << inet_ntoa(iad) << " Port:" << ntohs(udph.usSourPort) << std::endl; std::cout << "DestIP:" << inet_ntoa(iad) << " Port:" << ntohs(udph.usDestIPPort) << std::endl; std::cout << "recv data:" << szReadBuffer + 28 << std::endl; } closesocket(SocSrv); WSACleanup(); system("pause"); return 0; }
- 客户端:
#define _WINSOCK_DEPRECATED_NO_WARNINGS #include <iostream> #include <WinSock2.h> #pragma comment(lib,"ws2_32.lib") int main() { WORD wVerSionRequested = MAKEWORD(2, 2); WSAData lpWSAData; WSAStartup(wVerSionRequested, &lpWSAData); sockaddr_in saddr; saddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); saddr.sin_family = AF_INET; saddr.sin_port = htons(50123); SOCKET SocClient = socket(AF_INET, SOCK_DGRAM, 0); if (SocClient < 0) { return -1; } char opt; setsockopt(SocClient, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); char szSendBuffer[500]{ 0 }; std::cout << "input:"; std::cin >> szSendBuffer; sendto(SocClient, szSendBuffer, strlen(szSendBuffer), 0, (sockaddr*)&s5addr, sizeof(sockaddr)); WSACleanup(); closesocket(SocClient); WSACleanup(); system("pause"); return 0; }