1. 程式人生 > >UDP埠複用測試程式碼

UDP埠複用測試程式碼

具體不多說,看註釋。

// 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;
}