Select 多线程通信,模型实例

主要理解select函数,涉及到一些 宏和 数组定义


分为两端


Server端:


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

#include "stdafx.h"
#include <string.h>
#include <stdlib.h>

#include <Winsock2.h>
#pragma comment(lib,"Ws2_32.lib")


SOCKET gClientSockAddr[FD_SETSIZE]={0};
DWORD gClientSockNum = 0;
HANDLE ghMutex = NULL;
DWORD WINAPI RecvSendThead(LPVOID lpvoid);


DWORD WINAPI RecvSendThead(LPVOID lpvoid)
{
	timeval timeout = {3,0};
	
	while(TRUE)
	{
		DWORD ClientSockNum = gClientSockNum;
		if(ClientSockNum)
		{
			FD_SET readset;
			FD_ZERO (&readset);
			for(DWORD i=0;i<ClientSockNum;i++)
			{
				FD_SET(gClientSockAddr[i],&readset);
			}
			int ReadableNum = select(0,&readset,NULL,NULL,&timeout);
			
			if(ReadableNum == 0)
			{
				continue;
			}else{
				for(DWORD k = 0;k<ClientSockNum;k++)
				{
					if(FD_ISSET(gClientSockAddr[k],&readset))
					{
						char buf[MAX_PATH] = {0};
						int recvlen = recv(gClientSockAddr[k],buf,MAX_PATH,0);
						
						//if(strcmp(buf,"quit") == 0)
						if(strcmp(buf,"quit") == 0)
						{
							//断开
							shutdown(gClientSockAddr[k],SD_SEND);
							closesocket(gClientSockAddr[k]);
							WaitForSingleObject(ghMutex,INFINITE);
							gClientSockAddr[k] = gClientSockAddr[gClientSockNum-1];
							gClientSockAddr[gClientSockNum - 1] = NULL;
							gClientSockNum-=1;
							ReleaseMutex(ghMutex);
						}


						if(recvlen ==0 || recvlen == -1)
						{
							//断开
							shutdown(gClientSockAddr[k],SD_SEND);
							closesocket(gClientSockAddr[k]);
							WaitForSingleObject(ghMutex,INFINITE);
							gClientSockAddr[k] = gClientSockAddr[gClientSockNum-1];
							gClientSockAddr[gClientSockNum - 1] = NULL;
							gClientSockNum-=1;
							ReleaseMutex(ghMutex);
						}else{
							printf("Client Message: %s\n",buf);
							send(gClientSockAddr[k],buf,strlen(buf)+1,0);
							memset(buf,0,MAX_PATH);
						}

					}
				}
			}
		}
	}

	return 0;
}


int main(int argc, char* argv[])
{
	//0:初始化
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;
	wVersionRequested = MAKEWORD( 2, 2 );
 
	err = WSAStartup( wVersionRequested, &wsaData );
	if ( err != 0 ) {
		/* Tell the user that we could not find a usable */
		/* WinSock DLL.                                  */
		return 0;
	}

	//1 create socket
	SOCKET hSerSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	
	//2 bind
	struct sockaddr_in SerAddr={0};
	SerAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	SerAddr.sin_family = AF_INET;
	SerAddr.sin_port = htons(2018);
	bind(hSerSocket,(sockaddr*)&SerAddr,sizeof(SerAddr));

	//3 listen
	listen(hSerSocket,5);

	//4 accept

	
	ghMutex = CreateMutex(NULL,FALSE,NULL);

	HANDLE hThread = CreateThread(NULL,0,RecvSendThead,NULL,0,NULL);
	CloseHandle(hThread);

	while(TRUE)
	{
		struct sockaddr ClientAddr={0};
		int ClientAddrLen = sizeof(sockaddr);
		SOCKET hClientSocket = accept(hSerSocket,(sockaddr*)&ClientAddr,&ClientAddrLen);

		WaitForSingleObject(ghMutex,INFINITE);
		gClientSockAddr[gClientSockNum++] = hClientSocket;
		printf("第 %d 个客户进来\n",gClientSockNum);
		ReleaseMutex(ghMutex);
	}
	//5 send recv
	
	closesocket(hSerSocket);	
	WSACleanup();
	
	
	return 0;
}


Client客户端



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

#include "stdafx.h"
#include <Winsock2.h>

#pragma comment(lib,"Ws2_32.lib")

int main(int argc, char* argv[])
{
	/*
	创建套接字
	绑定套接字
	连接服务器
	收发数据
	断开连接(主动)
	关闭套接字
	*/
	
	//0:初始化
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;
	wVersionRequested = MAKEWORD( 2, 2 );
 
	err = WSAStartup( wVersionRequested, &wsaData );
	if ( err != 0 ) {
		/* Tell the user that we could not find a usable */
		/* WinSock DLL.                                  */
		return 0;
	}


	//1 create socket
	SOCKET hCliSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	//2 connet
	struct sockaddr_in SerAddr={0};
	SerAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	SerAddr.sin_family = AF_INET;
	SerAddr.sin_port = htons(2018);
	
	connect(hCliSocket,(sockaddr*)&SerAddr,sizeof(SerAddr));
	//3 send/recv
	char sendBuf[100]={0};
	while(TRUE)
	{
		scanf("%s",&sendBuf);
		if(strcmp(sendBuf,"quit")==0)
		{
			break;
		}
		send(hCliSocket,sendBuf,strlen(sendBuf)+1,0);
		char recvBuf[100]={0};
		recv(hCliSocket,recvBuf,100,0);
		printf("client: %s\n",recvBuf);
		
	}
	
	
	shutdown(hCliSocket,SD_RECEIVE);
	closesocket(hCliSocket);
	
	return 0;
}






原文链接: Select 多线程通信,模型实例 版权所有,转载时请注明出处,违者必究。
注明出处格式:流沙团 ( https://gyarmy.com/post-449.html )

发表评论

0则评论给“Select 多线程通信,模型实例”