Windows Socket UDP協議(服務器與客戶端)

這是一個常常用到的老掉牙的主題了,爲了之後用到方便,因此稍微註釋了一下而後放上來,代碼是本人修改過的,因此也就選成了「原創」。其實如今作碼農的,又有多少基礎模塊能說大致的代碼都是本身搞出來的呢?這個「原創"的界定很難!好了,廢話很少說,貼代碼,基本上用VS的拷過去也是能直接運行的。服務器

服務器普通實現代碼併發

<span style="color:#3366ff;">#include <stdio.h> 
#include <Winsock2.h> 

#pragma comment(lib,"Ws2_32.lib")//鏈接Sockets相關庫

void main()
{
	SOCKET socket1;
	WSADATA wsaData;
	if (WSAStartup(MAKEWORD(2, 1), &wsaData)) //初始化
	{
		printf("Winsock沒法初始化!\n");
		WSACleanup();
		return;
	}
	printf("服務器開始建立SOCKET。\n");
	struct sockaddr_in local;//本機地址相關結構體
	struct sockaddr_in from;//客戶端地址相關結構體
	int fromlen = sizeof(from);
	local.sin_family = AF_INET;
	local.sin_port = htons(27015); ///監聽端口 
	local.sin_addr.s_addr = INADDR_ANY; ///本機 
	socket1 = socket(AF_INET, SOCK_DGRAM, 0);
	bind(socket1, (struct sockaddr*)&local, sizeof(local));//綁定SOCKET,此步關鍵
	char buffer[1024] = "\0";
	if (recvfrom(socket1, buffer, sizeof(buffer), 0, (struct sockaddr*)&from, &fromlen) != SOCKET_ERROR)//阻塞接受客戶端的請求
	{
		printf("鏈接成功,開始發送數據\n");
	}
	while (1)
	{
		sendto(socket1, buffer, sizeof(buffer), 0, (struct sockaddr*)&from, fromlen);//發數據給客戶端,因爲是
		Sleep(200);
	}
	closesocket(socket1);
	WSACleanup();
}</span>

客戶端普通實現代碼

#include <stdio.h> 
#include <Winsock2.h> 

#pragma comment(lib,"Ws2_32.lib")//鏈接Sockets相關庫

void main()
{
	SOCKET socket1;
	WSADATA wsaData;
	if (WSAStartup(MAKEWORD(2, 1), &wsaData)) //初始化
	{
		printf("Winsock沒法初始化!\n");
		WSACleanup();
		return;
	}
	printf("客戶端開始建立SOCKET。\n");
	struct sockaddr_in server;
	int len = sizeof(server);
	server.sin_family = AF_INET;
	server.sin_port = htons(27015); ///server的監聽端口 
	server.sin_addr.s_addr = inet_addr("127.0.0.1"); ///server的地址 
	socket1 = socket(AF_INET, SOCK_DGRAM, 0);
	char buffer[1024] = "haha\0";
	if (sendto(socket1, buffer, sizeof(buffer), 0, (struct sockaddr*)&server, len) != SOCKET_ERROR)//發送信息給服務器,發送完進入等待,表明服務器在客戶端啓動前必須是等待狀態
	{
		printf("發送請求,等待客戶端接受併發送數據\n");
	}
	while (1)
	{
		Sleep(100);
		if (recvfrom(socket1, buffer, sizeof(buffer), 0, (struct sockaddr*)&server, &len) != SOCKET_ERROR)
		printf("從客戶端接收到的數據:%s\n", buffer);
	}
	closesocket(socket1);
	WSACleanup();

}


在程序設計中一般但願對於數據交互方有沒有數據傳來作出反應,而不是單純的阻塞等待在那裏。這個時候能夠用select先進行探測,一探測到有數據過來才調用recvfrom,若是超過期間則作出相應的超時處理,實現須要在上面的代碼中recvfrom(原程序該函數阻塞)處稍做修改,修改代碼以下:socket

fd_set readfds;
FD_ZERO(&readfds);//將指定的文件描述符集清空,在對文件描述符集合進行設置前,必須對其進行初始化,若是不清空,因爲在系統分配內存空間後,一般並不做清空處理,因此結果是不可知的
FD_SET(socket1, &readfds); //用於在文件描述符集合中增長一個新的文件描述符。
struct timeval tv_out;
tv_out.tv_sec = 5;//等待5秒
tv_out.tv_usec = 0;
int selright=select(socket1 + 1, &readfds, NULL, NULL, &tv_out);
if (selright<=0)//爲0時爲超時,小於0時爲錯誤,這兩種狀況皆非咱們所想,故作出相同的處理
{
	printf("鏈接失敗");
	return;
}
else
{
	if (recvfrom(socket1, buffer, sizeof(buffer), 0, (struct sockaddr*)&from, &fromlen) != SOCKET_ERROR)//阻塞接受客戶端的請求
	{
		printf("鏈接成功,開始發送數據\n");
	}
}
固然若是但願循環等待,則每次都必須從新設置readfds
相關文章
相關標籤/搜索