首页 > C/C++ > UDP广播搜索局域网服务器并获取IP
2014
02-15

UDP广播搜索局域网服务器并获取IP

功能简述:

服务端 使用UDP协议向255.255.255.255这个广播地址发送广播包,端口9936。
客户端 通过9936端口收到此广播包后,同时向服务器IP发送信息,从而双方都能建立起用户列表。

服务端代码

// 服务器端
// Server.cpp
//
#include <tchar.h>
#include <WinSock2.h>
#include <stdio.h>
#include <iostream>
#pragma comment(lib, "ws2_32.lib")

using namespace std;

const int MAX_BUF_LEN = 255;

int _tmain(int argc, _TCHAR* argv[])
{
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;

	// 初始化SOCKET
	wVersionRequested = MAKEWORD( 2, 2 );
	err = WSAStartup( wVersionRequested, &wsaData );
	if ( err != 0 )
	{
		return -1;
	}

	if ( LOBYTE( wsaData.wVersion ) != 2 ||	HIBYTE( wsaData.wVersion ) != 2 )
	{
		WSACleanup( );
		return -1; 
	}

	// 创建socket
	SOCKET connect_socket;
	connect_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if(INVALID_SOCKET == connect_socket)
	{
		err = WSAGetLastError();
		printf("socket error %d \n", err);
		return -1;
	}

	// 绑定套接字
	SOCKADDR_IN sin;
	sin.sin_family = AF_INET;
	sin.sin_port = htons(9936);
	sin.sin_addr.s_addr = INADDR_BROADCAST;


	//设置该套接字为广播类型,
	bool bOpt = true;
	setsockopt(connect_socket, SOL_SOCKET, SO_BROADCAST, (char*)&bOpt, sizeof(bOpt));

	// 绑定套接字
	err = bind(connect_socket, (SOCKADDR*)&sin, sizeof(SOCKADDR));
	if(SOCKET_ERROR == err)
	{
		err = WSAGetLastError();
		printf("bind error %d \n", err);
		return -1;
	}

	int nAddrLen = sizeof(SOCKADDR);
	char buff[MAX_BUF_LEN] = "";
	int nLoop = 0;

	// 接收数据
	int nRecvSize = recvfrom(connect_socket, buff, MAX_BUF_LEN, 0, (SOCKADDR*)&sin, &nAddrLen);
	if(SOCKET_ERROR == nRecvSize)
	{
		err = WSAGetLastError();
		printf("recvfrom error %d \n", err);
		return -1;
	}
	buff[nRecvSize] = '\0';

	// 接收数据之后就可以获取到对方IP
	char *pIPAddr = inet_ntoa(sin.sin_addr);
	int nPort = ntohs(sin.sin_port);

	printf("IpAddr: %s port: %d Recv: %s\n" , pIPAddr,nPort,buff);

	//向对方发一个包,以便对方能知道本机的真实IP
	strcpy(buff,"A");
	// 发送数据
	int nSendSize = sendto(connect_socket, buff, strlen(buff), 0, (SOCKADDR*)&sin, nAddrLen);
	if(SOCKET_ERROR == nSendSize)
	{
		err = WSAGetLastError();
		printf("sendto error %d \n", err);
		return -1;
	}

	return 0;
}

 

客户端代码

// 客户端
// Client.cpp
//
#include <tchar.h>
#include <WinSock2.h>
#include <stdio.h>
#include <iostream>
using namespace std;

#pragma comment(lib, "ws2_32.lib")

const int MAX_BUF_LEN = 255;

int _tmain(int argc, _TCHAR* argv[])
{
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;

	// 初始化SOCKET
	wVersionRequested = MAKEWORD( 2, 2 );
	err = WSAStartup( wVersionRequested, &wsaData );
	if ( err != 0 )
	{
		return -1;
	}

	if ( LOBYTE( wsaData.wVersion ) != 2 ||
		HIBYTE( wsaData.wVersion ) != 2 )
	{
		WSACleanup( );
		return -1; 
	}

	// 创建socket
	SOCKET connect_socket;
	connect_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if(INVALID_SOCKET == connect_socket)
	{
		err = WSAGetLastError();
		printf("socket error %d \n", err);
		return -1;
	}

	SOCKADDR_IN sin;
	sin.sin_family = AF_INET;
	sin.sin_port = htons(9936);
	sin.sin_addr.s_addr = INADDR_BROADCAST;

	bool bOpt = true;
	//设置该套接字为广播类型
	setsockopt(connect_socket, SOL_SOCKET, SO_BROADCAST, (char*)&bOpt, sizeof(bOpt));

	int nAddrLen = sizeof(SOCKADDR);

	char buff[MAX_BUF_LEN] = "";

	strcpy(buff,"A");

	// 发送数据
	int nSendSize = sendto(connect_socket, buff, strlen(buff), 0, (SOCKADDR*)&sin, nAddrLen);
	if(SOCKET_ERROR == nSendSize)
	{
		err = WSAGetLastError();
		printf("sendto error %d \n", err);
		return -1;
	}

	//这里第一次发送的是广播包地址是255.255.255.255
	char *pIPAddr = inet_ntoa(sin.sin_addr);
	int nPort = ntohs(sin.sin_port);
	printf("IpAddr: %s port: %d Send: %s\n" , pIPAddr,nPort,buff);

	// 接收数据之后就可以获取到对方的IP
	int nRecvSize = recvfrom(connect_socket, buff, MAX_BUF_LEN, 0, (SOCKADDR*)&sin, &nAddrLen);
	if(SOCKET_ERROR == nRecvSize)
	{
		err = WSAGetLastError();
		printf("recvfrom error %d \n", err);
		return -1;
	}
	buff[nRecvSize] = '\0';

	//获取到对方IP
	char *pIPAddr1 = inet_ntoa(sin.sin_addr);
	int nPort1 = ntohs(sin.sin_port);
	printf("IpAddr: %s port: %d Send: %s\n" , pIPAddr1,nPort1,buff);

	return 0;
}

 

参考文献
正确使用UDP广播(C++代码
http://blog.csdn.net/great3779/article/details/5699986

飞鸽传书文件传输实现原理
http://hi.baidu.com/extrazero/item/d77ed1ffa8dd92d642c36ad7

最后编辑:
作者:dnybz
这个作者貌似有点懒,什么都没有留下。