网络编程:广播

服务器端:

// Server.cpp : Defines the entry point for the console application.
//

#include "stdio.h"
#include <iostream>
using namespace std;
#include <string>
#include <WINSOCK2.H>
#pragma comment(lib, "wsock32.lib")

#define SERVER_EXIT_OK				0	//服务器正常退出
#define SERVER_DLL_REEOR			1	//调用Windows sockets DLL失败
#define SERVER_API_ERROR			2	//调用Windows sockets API失败
#define	SERVERPORT					5555//服务器TCP端口
#define MAX_NUM_BUF					64	//缓冲区最大尺寸

//变量
char	bufRecv[MAX_NUM_BUF];			//读缓冲区
char	bufSend[MAX_NUM_BUF];			//写缓冲区
SOCKET	sServer;						//服务器监听套接字

BOOL	bConning;						//与客户端的连接状态

//函数
void	InitMember(void);				//初始化成员变量 
int		ExitClient(int nExit);			//客户端退出
int		HandleSocketError(char *str);	//对Windows sockets API调用错误处理

//主函数
int main(int argc, char* argv[])
{

	InitMember();

	WORD	wVersionRequested;		//应用程序需要Windows sockets DLL的版本
	WSADATA	wsaData;				//Windows sockets DLL版本信息
	int		retVal;					//调用Windows sockets API返回值		
	//初始化Windows Sockets DLL
	wVersionRequested = MAKEWORD(1,1);
	retVal = WSAStartup(wVersionRequested, &wsaData);
	if ( 0 != retVal ) 
	{
		cout<<"Can not find a usable Windows Sockets dll!";
		return SERVER_DLL_REEOR;
	}	
	//确保WinSock DLL支持1.1
	if ( LOBYTE( wsaData.wVersion ) != 1 ||	HIBYTE( wsaData.wVersion ) != 1)
	{
		cout<<"Can not find a usable Windows Sockets dll!";
		WSACleanup( );
		return SERVER_DLL_REEOR; 
	}
	//创建一个数据报套接字用于发送广播信息
	sServer = socket(AF_INET, SOCK_DGRAM, 0);//UDP(SOCK_DGRAM)

	if(INVALID_SOCKET == sServer)
	{
		return HandleSocketError("Failed socket()!");
	}
	
	//设置广播选项,使SO_BROADCAST选项有效
	BOOL bBroadcast = true;
	setsockopt(sServer, SOL_SOCKET, SO_BROADCAST, 
                              (char*)&bBroadcast, sizeof(BOOL));
	/*sockfd:标识一个套接口的描述字。
  level:选项定义的层次;支持SOL_SOCKET、IPPROTO_TCP、IPPROTO_IP和IPPROTO_IPV6。
  optname:需设置的选项。
  optval:指针,指向存放选项值的缓冲区。
  optlen:optval缓冲区长度。*/

	//设置广播地址及广播端口号,这时的接收方地址应该设为地址INADDR_BROADCAST
	SOCKADDR_IN bcast;
	bcast.sin_addr.s_addr = INADDR_BROADCAST;  
                                                                  //::inet_addr("255.255.255.255");
	bcast.sin_family = AF_INET;
	bcast.sin_port = htons(SERVERPORT);

	//绑定套接字
	retVal = bind(sServer, (LPSOCKADDR)&bcast, sizeof(SOCKADDR_IN));


	printf(" 开始向网络中发送广播数据... \n \n");
	char sz[] = "This is just a test. \r\n";
	while(TRUE)
	{
		sendto(sServer, sz, strlen(sz), 0, (sockaddr*)&bcast, sizeof(bcast));
		/*s:一个标识套接口的描述字。
  buf:包含待发送数据的缓冲区。
  len:buf缓冲区中数据的长度。
  flags:调用方式标志位。
  to:(可选)指针,指向目的套接口的地址。
  tolen:to所指地址的长度。*/
		Sleep(5000);
	}
	//退出
	return ExitClient(SERVER_EXIT_OK);
}



/*
 *	初始化成员变量
 */
void	InitMember(void)
{
	//初始化读和写缓冲区
	memset(bufRecv, 0, MAX_NUM_BUF);
	memset(bufSend, 0, MAX_NUM_BUF);

	//初始化
	sServer = INVALID_SOCKET;

	//没有连接状态
	bConning = FALSE;
}
/*
 *	错误处理
 */
int		HandleSocketError(char *str)
{
	cout<<str;		//显示错误消息	
	WSACleanup();			//卸载Windows socket DLL	
	return SERVER_API_ERROR;//退出应用程序
}

/*
 *	退出
 */
int		ExitClient(int nExit)
{
	closesocket(sServer);	//关闭监听套接字
	WSACleanup();			//卸载Windows sockets DLL 清理内存
	return nExit;			//退出
}

	

客户端:

// Client.cpp : Defines the entry point for the console application.
//

#include "stdio.h"
#include <iostream>
using namespace std;
#include <string>
#include <WINSOCK2.H>
#pragma comment(lib, "wsock32.lib")

#define SERVER_EXIT_OK				0	//服务器正常退出
#define SERVER_DLL_REEOR			1	//调用Windows sockets DLL失败
#define SERVER_API_ERROR			2	//调用Windows sockets API失败
#define	SERVERPORT					5555//服务器TCP端口
#define MAX_NUM_BUF					64	//缓冲区最大尺寸

//变量
char	bufRecv[MAX_NUM_BUF];			//读缓冲区
char	bufSend[MAX_NUM_BUF];			//写缓冲区

SOCKET	sClient;						//接受客户端套接字
BOOL	bConning;						//与客户端的连接状态

//函数
void	InitMember(void);				//初始化成员变量 
int		ExitClient(int nExit);			//客户端退出
int		HandleSocketError(char *str);

//主函数
int main(int argc, char* argv[])
{

	InitMember();

	WORD	wVersionRequested;		//应用程序需要Windows sockets DLL的版本
	WSADATA	wsaData;				//Windows sockets DLL版本信息
	int		retVal;					//调用Windows sockets API返回值

	//初始化Windows Sockets DLL
	wVersionRequested = MAKEWORD(1,1);	
	retVal = WSAStartup(wVersionRequested,(LPWSADATA)&wsaData);
	if ( 0 != retVal ) 
	{
		cout<<"Error";
		//MessageBox(NULL, "Can not find a usable Windows Sockets dll!", "ERROR", MB_OK);
		return SERVER_DLL_REEOR;
	}

	//创建一个数据报套接字用于接收广播信息
	sClient = socket(AF_INET, SOCK_DGRAM, 0);
	if(INVALID_SOCKET == sClient)
	{
		return HandleSocketError("Failed socket()!");
	}

	LPHOSTENT hostEntry;
	char hostname[MAX_NUM_BUF];
	gethostname(hostname,MAX_NUM_BUF);			//获取主机名称
	hostEntry = gethostbyname(hostname);		//获取主机信息
	if(!hostEntry)
	{
;							//显示错误信息
		return ExitClient(SERVER_API_ERROR);	//退出
	}


	printf(" 开始接收广播数据... \n\n");

	//绑定一个本地地址,指明广播端口号(要和发送方设置端口号的相同)作为接收端口。
	SOCKADDR_IN addrRemote;	
	addrRemote.sin_family = AF_INET;
	addrRemote.sin_addr = *((LPIN_ADDR)*hostEntry->h_addr_list);
	//addrServ.sin_addr.s_addr = inet_addr("10.20.255.183");
	addrRemote.sin_port = htons(SERVERPORT);

	retVal = bind(sClient, (LPSOCKADDR)&addrRemote, sizeof(SOCKADDR_IN));

	int nLen = sizeof(addrRemote);
	char sz[256];
	while(TRUE)
	{
		int nRet = recvfrom(sClient, sz, 256, 0, (sockaddr*)&addrRemote, &nLen);
		/*sockfd:标识一个已连接套接口的描述字。 
  buf:接收数据缓冲区。 
  len:缓冲区长度。 
  flags:调用操作方式。是以下一个或者多个标志的组合体,可通过or操作连在一起:
		from:(可选)指针,指向装有源地址的缓冲区。 
  fromlen:(可选)指针,指向from缓冲区长度值。*/
		if(nRet > 0)
		{
			sz[nRet] = '\0';
			printf(sz);
		}
	}
	//退出
	return ExitClient(SERVER_EXIT_OK);
}



/*
 *	初始化成员变量
 */
void	InitMember(void)
{
	//初始化读和写缓冲区
	memset(bufRecv, 0, MAX_NUM_BUF);
	memset(bufSend, 0, MAX_NUM_BUF);

	//初始化
	sClient = INVALID_SOCKET;

	//没有连接状态
	bConning = FALSE;
}

/*
 *	错误处理
 */
int		HandleSocketError(char *str)
{
	cout<<str;		//显示错误消息	
	WSACleanup();			//卸载Windows socket DLL	
	return SERVER_API_ERROR;//退出应用程序
}
/*
 *	退出
 */
int		ExitClient(int nExit)
{
	closesocket(sClient);	//关闭连接客户端套接接
	WSACleanup();			//卸载Windows sockets DLL 清理内存
	return nExit;			//退出
}

	

服务器端:


客户端:




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值