UDP端口复用测试代码

具体不多说,看注释。

// udp.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include 
#include 
#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;
}



你可能感兴趣的:(网络编程)