UDP埠複用測試程式碼
阿新 • • 發佈:2019-02-14
具體不多說,看註釋。
// udp.cpp : 定義控制檯應用程式的入口點。 // #include "stdafx.h" #include <windows.h> #include <winsock2.h> #pragma comment(lib,"ws2_32.lib") int _tmain(int argc, _TCHAR* argv[]) { WORD ver = MAKEWORD(2,2); WSAData data; if (WSAStartup(ver,&data)!=0) { printf("WSAStartup() error:%d\n",WSAGetLastError()); return -1; } SOCKET s = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); SOCKET s1 = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); if (s==INVALID_SOCKET) { printf("socket() error:%d",WSAGetLastError()); return -1; } if(s1==INVALID_SOCKET) { printf("socket() error:%d",WSAGetLastError()); return -1; } // 兩個都都要設定埠複用 int flag = 1; if(setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char*)&flag,sizeof(flag))==SOCKET_ERROR) { printf("setsockopt for s error:%d",WSAGetLastError()); } if(setsockopt(s1,SOL_SOCKET,SO_REUSEADDR,(char*)&flag,sizeof(flag))==SOCKET_ERROR) { printf("setsockopt for s1 error:%d",WSAGetLastError()); } // 一些常規變數 char buff[256]; struct sockaddr_in sin; int portbase = 15008; int len = sizeof(sin); int size; sin.sin_addr.s_addr = INADDR_ANY; sin.sin_family = AF_INET; sin.sin_port = htons(portbase); // 第一次迴圈繫結,直到成功,入站地址使用INADDR_ANY while (bind(s,(struct sockaddr*)&sin,sizeof(sin))==SOCKET_ERROR) { printf("bind() s port:%d error:%d\n",portbase,WSAGetLastError()); portbase++; sin.sin_port = htons(portbase); } // 第二次繫結,需要用其他地址,入站地址用本地網絡卡的LAN地址 sin.sin_addr.s_addr = inet_addr("192.168.1.147"); if (bind(s1,(struct sockaddr*)&sin,sizeof(sin))==SOCKET_ERROR) { printf("bind() s1 port:%d error:%d\n",portbase,WSAGetLastError()); } // 通過實驗發現,直接繫結本地網絡卡LAN地址在接收上有優先順序,埠複用後只有一個SOCKET能正常接收 while(true) { ZeroMemory(&sin,len); size = recvfrom(s1,buff,256,0,(sockaddr*)&sin,&len); if(size>0) { buff[size]=0; printf("s1 msg: len=%d %s\n",size,buff); } sockaddr_in toAddr; toAddr.sin_family = AF_INET; toAddr.sin_port = htons(15009); toAddr.sin_addr.s_addr = inet_addr("192.168.1.147"); // 兩個SOCKET都能正常傳送 sendto(s,"hello\r\n",7,0,(struct sockaddr*)&toAddr,sizeof(toAddr)); sendto(s1,"world\r\n",7,0,(struct sockaddr*)&toAddr,sizeof(toAddr)); } return 0; }