基於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);	// 向服務器發送數據 


發佈了3 篇原創文章 · 獲贊 12 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章