【Windows网络编程】Select网络模型

#include <WinSock2.h>
#include <stdio.h>
#define PORT 6000
#pragma comment (lib, "Ws2_32.lib")
fd_set g_fdClientSock;         //file discriotin set集合
int clientNum = 0;
BOOL WinSockInit()
{
	WSADATA data = { 0 };
	if (WSAStartup(MAKEWORD(2, 2), &data))
		return FALSE;
	if (LOBYTE(data.wVersion) != 2 || HIBYTE(data.wVersion) != 2)
	{
		WSACleanup();
		return FALSE;
	}
	return TRUE;
}
DWORD WINAPI ListenThreadProc(LPARAM lparam)
{
	fd_set fdRead;
	FD_ZERO(&fdRead);
	int nRet = 0;
	char* recvBuffer = (char*)malloc(sizeof(char)* 1024);
	if (NULL == recvBuffer)
	{
		return -1;
	}
	memset(recvBuffer, 0, sizeof(char)* 1024);
	while (true)
	{
		fdRead = g_fdClientSock;
		timeval tv;
		tv.tv_sec = 1;
		tv.tv_usec = 0;
		//select操作会阻塞的检查整个FD_SET数组里面的所有soket是否有信号来了
		//解决了标准TCP n个客户就要n+1个线程的问题
		//线程时间片没有充分利用
		nRet = select(0, &fdRead, NULL, NULL, &tv);      //sleep将线程休眠操作
		if (nRet != SOCKET_ERROR)
		{
			//找到数组内哪个sokect有信号
			for (int i = 0; i < g_fdClientSock.fd_count; i++)
			{
				//遍历有哪些sokect有数据信号到达
				if (FD_ISSET(g_fdClientSock.fd_array[i], &fdRead))
				{
					//与客户通信
					memset(recvBuffer, 0, sizeof(char)* 1024);
					nRet=(recv(g_fdClientSock.fd_array[i], recvBuffer, 1024, 0));
					if (nRet == SOCKET_ERROR)
					{
						closesocket(g_fdClientSock.fd_array[i]);
						clientNum--;
						FD_CLR(g_fdClientSock.fd_array[i], &g_fdClientSock);
					}
					else if (nRet==0)
					{
						closesocket(g_fdClientSock.fd_array[i]);
						clientNum--;
						FD_CLR(g_fdClientSock.fd_array[i], &g_fdClientSock);
					}
					else
					{
						//todo:后续处理
						printf("Recv msg:%s\n", recvBuffer);
						send(g_fdClientSock.fd_array[i], recvBuffer, strlen(recvBuffer), 0);
					}
				}
			}
		}
	}
	if (recvBuffer != NULL)
		free(recvBuffer);
	return 0;
}
int main()
{
	WinSockInit();
	SOCKET ListenSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	struct sockaddr_in server;
	server.sin_family = AF_INET;
	server.sin_addr.s_addr = htonl(INADDR_ANY);
	server.sin_port = htons(PORT);

	int ret = bind(ListenSock, (sockaddr*)&server, sizeof(server));
	ret = listen(ListenSock, 4);

	sockaddr_in clientAddr;
	int nameLen = sizeof(clientAddr);
	//先把服务器创建起来
	CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ListenThreadProc, NULL, NULL, NULL);
	//主线程里面开始进行Accept操作
	while (clientNum < FD_SETSIZE)  //FD_SETSIZE=64
	{
		//当有一个客户端进行连接时,主线程的Accept会进行返回
		SOCKET clientSock = accept(ListenSock, (sockaddr*)&clientAddr, &nameLen);
		
		FD_SET(clientSock, &g_fdClientSock);
		
		clientNum++;
	}
	closesocket(ListenSock);
	WSACleanup();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值