zoukankan      html  css  js  c++  java
  • 利用异步通知I/O模型实现回声服务器端(windows)

    #include <stdio.h>
    #include <string.h>
    #include <winsock2.h>
    
    #define BUF_SIZE 100
    
    void CompressSockets(SOCKET hSockArr[], int idx, int total);
    void CompressEvents(WSAEVENT hEventArr[], int idx, int total);
    void ErrorHanding(char *msg);
    
    int main(int argc, char *argv[])
    {
    	WSADATA wsaData;
    	SOCKET hServSock, hClntSock;
    	SOCKADDR_IN servAdr, clntAdr;
    
    	SOCKET hSockArr[WSA_MAXIMUM_WAIT_EVENTS];
    	WSAEVENT hEventArr[WSA_MAXIMUM_WAIT_EVENTS];
    	WSAEVENT newEvent;
    	WSANETWORKEVENTS netEvents;
    
    	int numOfClntSock = 0;
    	int strLen, i;
    	int postInfo, startIdx;
    	int clntAdrLen;
    	char msg[BUF_SIZE];
    
    	if (argc != 2)
    	{
    		printf("Usage: %s <port>
    ", argv[0]);
    		exit(1);
    	}
    	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    		ErrorHanding("WSAStartUp() error!");
    
    	hServSock = socket(AF_INET, SOCK_STREAM, 0);
    	memset(&servAdr, 0, sizeof(servAdr));
    	servAdr.sin_family = AF_INET;
    	servAdr.sin_addr.s_addr = htonl(INADDR_ANY);
    	servAdr.sin_port = htons(atoi(argv[1]));
    
    	if (bind(hServSock, (SOCKADDR *) &servAdr, sizeof(servAdr)) == SOCKET_ERROR)
    		ErrorHanding("bind() error");
    
    	if (listen(hServSock, 5) == SOCKET_ERROR)
    		ErrorHanding("listen() error");
    
    	newEvent = WSACreateEvent();
    	if (WSAEventSelect(hServSock, newEvent, FD_ACCEPT) == SOCKET_ERROR)
    		ErrorHanding("WSAEventSelect() error");
    
    	hSockArr[numOfClntSock] = hServSock;
    	hEventArr[numOfClntSock] = newEvent;
    	numOfClntSock ++;
    
    	while (1)
    	{
    		postInfo = WSAWaitForMultipleEvents(numOfClntSock, hEventArr, FALSE, INFINITE, FALSE);
    		startIdx = postInfo - WSA_WAIT_EVENT_0;
    
    		for (i = startIdx; i < numOfClntSock; i++)
    		{
    			int sigEventIdx = WSAWaitForMultipleEvents(1, &hEventArr[i], TRUE, 0, FALSE);
    			if (sigEventIdx == WSA_WAIT_FAILED || WSA_WAIT_TIMEOUT)
    			{
    				continue;
    			}
    			else
    			{
    				sigEventIdx = i;
    				WSAEnumNetworkEvents(hSockArr[sigEventIdx], hEventArr[sigEventIdx], &netEvents);
    				if (netEvents.lNetworkEvents & FD_ACCEPT) //请求连接时
    				{
    					if (netEvents.iErrorCode[FD_ACCEPT_BIT] != 0)
    					{
    						puts("Accept Error");
    						break;
    					}
    					clntAdrLen = sizeof(clntAdr);
    					hClntSock = accept(hSockArr[sigEventIdx], (SOCKADDR *)&clntAdr, &clntAdrLen);
    					newEvent = WSACreateEvent();
    					WSAEventSelect(hClntSock, newEvent, FD_READ | FD_CLOSE);
    
    					hEventArr[numOfClntSock] = newEvent;
    					hSockArr[numOfClntSock] = hClntSock;
    					numOfClntSock++;
    					puts("connected new client ...");
    				}
    
    				if (netEvents.lNetworkEvents & FD_READ) //接收数据时
    				{
    					if (netEvents.iErrorCode[FD_READ_BIT] != 0)
    					{
    						puts("Read Error");
    						break;
    					}
    					strLen = recv(hSockArr[sigEventIdx], msg, sizeof(msg), 0);
    					send(hSockArr[sigEventIdx], msg, strLen, 0);
    				}
    
    				if (netEvents.lNetworkEvents & FD_CLOSE) //断开连接时
    				{
    					if (netEvents.iErrorCode[FD_CLOSE_BIT] != 0)
    					{
    						puts("Close Error");
    						break;
    					}
    					WSACloseEvent(hEventArr[sigEventIdx]);
    					closesocket(hSockArr[sigEventIdx]);
    
    					numOfClntSock --;
    					CompressSockets(hSockArr, sigEventIdx, numOfClntSock);
    					CompressEvents(hEventArr, sigEventIdx, numOfClntSock);
    				}
    			}
    		}
    	}
    	WSACleanup();
    	return 0;
    } // end of main function
    
    void CompressSockets(SOCKET hSockArr[], int idx, int total)
    {
    	int i;
    	for (i = idx; i < total; i++)
    		hSockArr[i] = hSockArr[i + 1];
    }
    
    void CompressEvents(WSAEVENT hEventArr[], int idx, int total)
    {
    	int i;
    	for (i = idx; i < total; i++)
    		hEventArr[i] = hEventArr[i + 1];
    }
    
    void ErrorHanding(char *msg)
    {
    	fputs(msg, stderr);
    	fputc('
    ', stderr);
    	exit(1);
    }
    

    别忘了,项目中需要添加ws2_32.lib

  • 相关阅读:
    WinRAR5.01注册码附注册机
    PS不能存储,因为程序错误
    mysql中 date datetime time timestamp 的区别
    sublime text 3 3126 注册码+中文包
    IIS7.5 用 IIS AppPool应用程序池名 做账号 将各站点权限分开
    linux vi 报错 E37: No write since last change (add ! to override)
    Linux 安装 apache2.4.23
    三级分类及名称及列表
    二级栏目名称及列表
    每隔N行输出不同样式
  • 原文地址:https://www.cnblogs.com/wisdomroc/p/11857556.html
Copyright © 2011-2022 走看看