基于UDP的select函数用法

/************SERVER**************/
#include 
#include 
#define PORT_A	11111
#define PORT_B  22222
void main(int argc, char **argv)
{
	WSADATA wsaData; // 套接口信息数据
	SOCKET socka;	// 套接口a
	SOCKET sockb;	// 套接口b
	
	int nPortA = PORT_A;
	int nPortB = PORT_B;
	fd_set rfd;		// 读描述符集
	timeval timeout;	// 定时变量
	sockaddr_in addr; // 告诉sock 应该在什么地方licence
	char recv_buf[1024];	// 接收缓冲区
	
	int nRecLen; // 客户端地址长度!!!!!!
	
	sockaddr_in cli;	// 客户端地址
	int nRet; // select返回值
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
	{
		printf("failed to laod winsock!/n");
		return;
	}
	socka = socket(AF_INET, SOCK_DGRAM, 0);	// 创建数据报socka
	if (socka == INVALID_SOCKET)
	{
		printf("socket()/n");
		return;
	}
	sockb = socket(AF_INET, SOCK_DGRAM, 0);	// 创建数据报sockb
	if (sockb == INVALID_SOCKET)
	{
		printf("socket()/n");
		return;
	}
	memset(&addr, 0, sizeof(addr));
	
	addr.sin_family = AF_INET;	 // IP协议
	addr.sin_port = htons(nPortA); // 端口
	addr.sin_addr.s_addr = htonl(INADDR_ANY); // 在本机的所有ip上开始监听
	if (bind(socka, (sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR)// bind socka
	{
		printf("bind()/n");
		return;
	}
	
	memset(&addr, 0, sizeof(addr));
	addr.sin_family = AF_INET;	 // IP协议
	addr.sin_port = htons(nPortB); // 端口
	addr.sin_addr.s_addr = htonl(INADDR_ANY); // 在本机的所有ip上开始监听
	
	if (bind(sockb, (sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) // bind sockb
	{
		printf("bind()/n");
		return;
	}
	// 设置超时时间为6s
	timeout.tv_sec = 6;	
	timeout.tv_usec = 0;
	
	memset(recv_buf, 0, sizeof(recv_buf)); // 清空接收缓冲区
	while (true)
	{
		FD_ZERO(&rfd); // 在使用之前总是要清空
		
		// 开始使用select
		FD_SET(socka, &rfd); // 把socka放入要测试的描述符集中
		FD_SET(sockb, &rfd); // 把sockb放入要测试的描述符集中
		
		nRet = select(0, &rfd, NULL, NULL, &timeout);// 检测是否有套接口是否可读
		if (nRet == SOCKET_ERROR)	
		{
			printf("select()/n");
			return;
		}
		else if (nRet == 0)	// 超时
		{
			printf("timeout/n");
			closesocket(socka);
			closesocket(sockb);
			break;
		}
		else	// 检测到有套接口可读
		{
			if (FD_ISSET(socka, &rfd))	// socka可读
			{
				nRecLen = sizeof(cli);
				int nRecEcho = recvfrom(socka, recv_buf, sizeof(recv_buf), 0, (sockaddr*)&cli, &nRecLen);
				if (nRecEcho == INVALID_SOCKET)
				{
					printf("recvfrom()/n");
					break;
				}
				printf("data to port 11111: %s/n", recv_buf);
			}
			if (FD_ISSET(sockb, &rfd)) // sockb 可读
			{
				nRecLen = sizeof(cli);
				int nRecEcho = recvfrom(sockb, recv_buf, sizeof(recv_buf), 0, (sockaddr*)&cli, &nRecLen);
				if (nRecEcho == INVALID_SOCKET)
				{
					printf("recvfrom()/n");
					break;
				}
				printf("data to port 22222: %s/n", recv_buf);
			}
		}
	}
	WSACleanup();
}

/************CLIENT*************/
#include 
#include 
#include 
#define SERVER_PORT_A 11111		// 服务器端口A
#define SERVER_PORT_B 22222		// 服务器端口B
typedef struct tagSERVER	// 服务器
{
	char* ip;	// ip地址
	int nPort;	// 端口号
} SERVER, *PSERVER;	
int SendData(SOCKET s, char *ip, int nPort, char *pData); // 发送数据到IP:nPort
int main(int argc, char **argv)
{
	int i;
	WSADATA wsaData;		// socket数据
	SOCKET sClient;			// 客户端套接口
	char send_buf[] = "hello! I am LiangFei whoes SNO=06060734";	// 发送的数据内容
	int nSend; // 发送数据后的返回值
	// 服务器
	SERVER sers[] = {	{"127.0.0.1", SERVER_PORT_A}, 
						{"127.0.0.1", SERVER_PORT_B} };
	int nSerCount = sizeof(sers) / sizeof(sers[0]); // 服务器个数
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)	// 启动socket
	{
		printf("failed to start up socket!/n");
		return 0;
	}
	
	// 建立客户端数据包套接口
	sClient = socket(AF_INET, SOCK_DGRAM, 0);
	if (sClient == INVALID_SOCKET)
	{
		printf("socket()/n");
		return 0;
	}
	for (i = 0; i < nSerCount; i++)
	{
		nSend = SendData(sClient, sers[i].ip, sers[i].nPort, send_buf);	// 发送数据
		if (nSend == 0)	// 发送失败
		{
			return 0;
		}
		else if (nSend == SOCKET_ERROR)	// 套接口出错
		{
			printf("sendto()/n");
			return 0;
		}
	}
	closesocket(sClient);	// 关闭套接口
	WSACleanup(); // 卸载winsock
	return 0;
}
int SendData(SOCKET s, char *ip, int nPort, char *pData)
{
	sockaddr_in ser;	// 服务器端地址	
	ser.sin_family = AF_INET;	// IP协议
	ser.sin_port = htons(nPort);	// 端口号
	ser.sin_addr.s_addr = inet_addr(ip);	// IP地址
	int nLen = sizeof(ser);	// 服务器地址长度
	
	return sendto(s, pData, strlen(pData) + 1, 0, (sockaddr*)&ser, nLen);	// 向服务器发送数据 


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