UDP广播测试端口复用 SO_REUSEADDR

 

#define LOG_TAG "ut_SocketReusePort"

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace twl;

int srp_startSink();
int srp_startSrc();

class server:public Handler
{
public:
	server(){};
	  ~server(){};
protected:
	void onMessageReceived(const sp &msg){
		srp_startSink();
	}
};

class client:public Handler
{
public:
	client(){};
	~client(){};
protected:
	void onMessageReceived(const sp &msg){
		srp_startSrc();
	}
};

//////////////////////////////////////////////////////////////////////////
void srp_start_test(){
	net_Init();
	sp servServer1 = new server();
	sp servServer2 = new server();

	sp servClient = new client();

	sp looperServer1 = new Looper();
	sp looperServer2 = new Looper();

	sp looperClient1 = new Looper();

	looperServer1->registerHandler(servServer1);
	looperServer2->registerHandler(servServer2);
	Sleep(2000);//wait for server start up.
	looperClient1->registerHandler(servClient);

	looperServer1->start();
	looperServer2->start();
	looperClient1->start();

	sp msg1 = new Message();
	msg1->setTarget(servServer1->id());
	msg1->post();
	msg1->setTarget(servServer2->id());
	msg1->post();


	sp msg2 = new Message(0,servClient->id());
	msg2->post();

	while(getchar());
}

#define  SOKCET_SINK_PORT			(76364)
#define  SOCKET_BUFFER_SIZE		(1024 * 100)
//////////////////////////////////////////////////////////////////////////
int srp_startSink(){
	int res;
	sockaddr_in in;
	memset(&in,0x00,sizeof(in));
	in.sin_family=AF_INET;
	in.sin_port=htons(SOKCET_SINK_PORT);
	in.sin_addr.s_addr=INADDR_ANY;

	int fd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
	if(fd <= -1){
		printf("socket error:%d\n",net_errno);
		return net_errno;
	}
	res = net_setSockoptInt( fd, SOL_SOCKET, SO_BROADCAST, 1);
	if (res < 0) {
		return net_errno;
	}

	printf("创建socket(%d)\n",fd);

	if(net_SetNonBlock(fd,0) <= -1)
		return -1;
	int nOptval;
	res = net_setSockoptInt( fd, SOL_SOCKET, SO_REUSEADDR, 1);
	if (res < 0) {
		printf("socket error:%d\n",net_errno);
		return net_errno;
	}
	res = net_setSockoptInt( fd, SOL_SOCKET, SO_RCVBUF, SOCKET_BUFFER_SIZE);
	if (res < 0) {
		printf("socket error:%d\n",net_errno);
		return net_errno;
	}

	res = net_setSockoptInt(fd, SOL_SOCKET, SO_SNDBUF, SOCKET_BUFFER_SIZE);
	if (res < 0) {
		printf("socket error:%d\n",net_errno);
		return net_errno;
	}
		
	// 绑定这个套节字到一个本地地址
	if(::bind(fd, (LPSOCKADDR)&in, sizeof(in)) == SOCKET_ERROR)
	{
		printf("Failed bind() \n");
		return 0;
	}

	printf("等待接收数据socket(%d)\n",fd);

	long lRecOnce = 0;
	sockaddr_in addr;
	int addrlen = sizeof(addr);
	CHAR szRecvBuf[SOCKET_BUFFER_SIZE];	
	while (1)
	{
		lRecOnce = ::recvfrom(fd, szRecvBuf, SOCKET_BUFFER_SIZE, 0, (sockaddr*)&addr, &addrlen); 
		if (lRecOnce<=0)
			return -1;
		szRecvBuf[lRecOnce] = '\0';
		printf("接收到数据 socket:%d:%s", fd, szRecvBuf);
	}
	
	return -1;
}





//////////////////////////////////////////////////////////////////////////

int srp_startSrc(){
	int res;
	int fd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
	res = net_setSockoptInt( fd, SOL_SOCKET, SO_BROADCAST, 1);
	if (res < 0) {
		printf("socket error:%d\n",net_errno);
		return net_errno;
	}
	res = net_setSockoptInt( fd, SOL_SOCKET, SO_REUSEADDR, 1);
	if (res < 0) {
		printf("socket error:%d\n",net_errno);
		return net_errno;
	}
	res = net_setSockoptInt( fd, SOL_SOCKET, SO_RCVBUF, SOCKET_BUFFER_SIZE);
	if (res < 0) {
		printf("socket error:%d\n",net_errno);
		return net_errno;
	}

	res = net_setSockoptInt(fd, SOL_SOCKET, SO_SNDBUF, SOCKET_BUFFER_SIZE);
	if (res < 0) {
		printf("socket error:%d\n",net_errno);
		return net_errno;
	}

	// 填写远程地址信息
	sockaddr_in addr; 
	addr.sin_family = AF_INET;
	addr.sin_port = htons(SOKCET_SINK_PORT);
	addr.sin_addr.S_un.S_addr = INADDR_BROADCAST;

	for (;;)
	{
		// 发送数据
		char szText[] = " socket packet test.\r\n";
		int sendOnce = ::sendto(fd, szText, strlen(szText), 0, (sockaddr*)&addr, sizeof(addr));
		if(sendOnce <= -1){
			printf("socket error:%d\n",net_errno);
			return net_errno;
		}
		printf("发送出数据(%s):%s", ::inet_ntoa(addr.sin_addr), szText);
		Sleep(2000);
	}

	::closesocket(fd);
	return -1;
}

你可能感兴趣的