windows select

第一步 :双线程


// SelectServer.cpp


#include <windows.h>
#include <stdio.h>
#include <winsock2.h>


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


DWORD WINAPI SelectProc(LPVOID lpParameter)
{
if (NULL == lpParameter)
{
printf("invalid thread param!\n");
return -1;
}


SOCKET sAccept = *(SOCKET*)(lpParameter);
char szRecv[4096] = {0};

fd_set fdRead;
fd_set fdWrite;
fd_set fdExcept;
timeval time;
time.tv_sec = INFINITE;
time.tv_usec = 0;


for ( ; ;)
{
FD_ZERO(&fdRead);

FD_SET(sAccept, &fdRead);   // 1.这个要放在select 前,每次都要处理的


int nRet = select(0, &fdRead, NULL, NULL, &time/*NULL*/);
if (SOCKET_ERROR == nRet)
{
DWORD dwLastErr = WSAGetLastError();
printf("select socket error! err: %u\n", dwLastErr);
break;
}




if( FD_ISSET( sAccept, &fdRead ) )
//if (fdRead.fd_array[0] == sAccept)
{
printf("select a read socket\n");
nRet = recv(sAccept, szRecv, 4096, 0);
if (SOCKET_ERROR != nRet)
{
printf("recv data: %s\n", szRecv);
}

nRet = send(sAccept, szRecv, strlen(szRecv), 0);
if (SOCKET_ERROR == nRet)
{
printf("send data error\n");
break;
}

printf("send data: %s\n", szRecv);


FD_CLR( sAccept , &fdRead );
closesocket(sAccept);
sAccept = INVALID_SOCKET;
}






if (INVALID_SOCKET == sAccept)
{
printf("I'm INVALID_SOCKET ,I will return\n");
return 0;
}

}

if (INVALID_SOCKET != sAccept)
{
closesocket(sAccept);
sAccept = INVALID_SOCKET;
}

printf("thread exit\n");

return 0;
}


int main()
{
DWORD dwVersion = 0;
WSADATA wsaData;
DWORD dwErr = 0;
int kk =0;
dwErr = WSAStartup(MAKEWORD(0x2, 0x2), &wsaData);
if (0 != dwErr)
{
printf("winsock init error!\n");
return -1;
}


if (0x2 != LOBYTE(wsaData.wVersion) ||
0x2 != HIBYTE(wsaData.wVersion))
{
// couldn't find a usable WinSock DLL.
printf("request winsock version error!\n");
WSACleanup();
return -1;
}


//SOCKET sAccept = INVALID_SOCKET;


SOCKET sAccept[512] = {INVALID_SOCKET}; //这个要注意,如果只用一个会覆盖,因为可能多个连接


SOCKET sListen = socket(AF_INET, SOCK_STREAM, 0);
if (INVALID_SOCKET == sListen)
{
printf("create a socket error!\n");
WSACleanup();
return -1;
}


sockaddr_in servAddr;
ZeroMemory(&servAddr, sizeof(servAddr));
servAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
servAddr.sin_family = AF_INET;
servAddr.sin_port = htons(80);


sockaddr_in clientAddr;
ZeroMemory(&clientAddr, sizeof(clientAddr));
int nLen = sizeof(clientAddr);


DWORD dwThreadID = 0;
HANDLE hThread = NULL;

if (SOCKET_ERROR == bind(sListen, (struct sockaddr*)&servAddr, sizeof(servAddr)))
{
printf("bind socket error!\n");
dwErr = WSAGetLastError();
goto _QUIT;
}


if (SOCKET_ERROR == listen(sListen, SOMAXCONN))
{
printf("listen socket error!\n");
dwErr = WSAGetLastError();
goto _QUIT;
}


printf("listen......\n");




while (1)
{
sAccept[kk] = accept(sListen, (sockaddr *)&clientAddr, &nLen);
if (INVALID_SOCKET == sAccept[kk])
{
printf("accept a socket error!\n");
dwErr = WSAGetLastError();
break;
}

printf("accept a socket\n");
hThread = CreateThread(NULL, 0, SelectProc, &sAccept[kk], 0, &dwThreadID);
if (NULL == hThread)
{
printf("create thread error!\n");
dwErr = -1;
goto _QUIT;
}
kk++;
}



_QUIT:


if (INVALID_SOCKET != sListen)
{
closesocket(sListen);
sListen = INVALID_SOCKET;
}


WSACleanup();
return dwErr;
}


这样,并不是完全的异步方式


异步单线程


#include <stdio.h>
#include <string.h>
#include <WINSOCK2.H>

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

#define STR_SERVER_IP           "127.0.0.1"
#define INT_SERVER_PORT         80
#define INT_DATABUFFER_SIZE     2560



bool reachDelayTime(SYSTEMTIME nowTime,SYSTEMTIME startTime)
{
	//是先算后面的吗
	if (nowTime.wYear>startTime.wYear ||
		nowTime.wMonth > startTime.wMonth ||
		nowTime.wDay>startTime.wDay||
		nowTime.wHour> startTime.wHour||
		nowTime.wMinute>startTime.wMinute||
		nowTime.wSecond>=(startTime.wSecond+2))   //>=2s 实际为1s以上
	{
		return true;
	}
	return false;
}


int main(int argc, char* argv[])
{


	SYSTEMTIME startT,nowT;

    GetLocalTime(&startT);

	
/*
	printf("now1 %d %d \n",startT.wSecond,startT.wMilliseconds );
	Sleep(1);
	 GetLocalTime(&nowT);
	 nowT.wMonth = startT.wMonth+0;
	printf("now2 %d %d \n",nowT.wSecond,nowT.wMilliseconds );


	printf("reachDelayTime=%d \n",reachDelayTime(nowT,startT) );
	//printf("now2 %d \n",time2 );

	return 1;
*/

    WORD dwVersion = MAKEWORD(2,2);
    WSAData wsaData;
    WSAStartup(WINSOCK_VERSION,&wsaData);

    SOCKET sockServer = socket(AF_INET, SOCK_STREAM, 0);
    if (INVALID_SOCKET == sockServer) {
        printf("Failed to create socket!\r\n");
        WSACleanup();
        return -1;
    }
	
    sockaddr_in addrServer;
    memset(&addrServer,0,sizeof(sockaddr_in));
    addrServer.sin_family = AF_INET;
    addrServer.sin_port = htons(INT_SERVER_PORT);
    addrServer.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
    //addrServer.sin_addr.s_addr = htonl(INADDR_ANY);

    int iResult;

    bool bReuseAddr = true;
    iResult=setsockopt(sockServer,SOL_SOCKET,SO_REUSEADDR,(char *)&bReuseAddr,sizeof(bReuseAddr));
    if(SOCKET_ERROR == iResult) {
        printf("Failed to set resueaddr socket!\r\n");
        WSACleanup();
        return -1;
    }
	
    
    //unsigned   long cmd = 1;
   // iResult= ioctlsocket(sockServer,FIONBIO,&cmd); 

    iResult = bind(sockServer,(sockaddr *)&addrServer,sizeof(addrServer));
    if (SOCKET_ERROR == iResult) {
        printf("Failed to bind address!\r\n");
        WSACleanup();
        return -1;
    }

    if (0 != listen(sockServer,5)) {
        printf("Failed to listen client!\r\n");
        WSACleanup();
        return -1;
    }

    UINT i = 0;
    SOCKET sockAccept;
    sockaddr_in addrAccept;
    int iAcceptLen = sizeof(addrAccept);
    char szDataBuff[INT_DATABUFFER_SIZE];
    int iRecvSize;
    
	int t1 = INVALID_SOCKET;

	SOCKET sAccept[512] = {INVALID_SOCKET}; //这个要注意,如果只用一个会覆盖,因为可能多个连接

	memset(sAccept,INVALID_SOCKET,512*sizeof(SOCKET));

    sockaddr_in addrTemp;
    int iTempLen;

    fd_set fdRead;


    
    timeval tm;
    tm.tv_sec = 0;
    tm.tv_usec = 1000;
    
    printf("Start server...\r\n");

	int iTemp=0;
    while(1) 
	{
		FD_ZERO(&fdRead);
		FD_SET(sockServer, &fdRead);


		//printf("INVALID_SOCKET %d \n",INVALID_SOCKET);
		for( iTemp=0;iTemp<512;iTemp++)
		{
			if (sAccept[iTemp] != INVALID_SOCKET )
			{
				FD_SET(sAccept[iTemp], &fdRead);
			}
		}


        iResult = select(0, &fdRead, NULL, NULL,&tm/*NULL*/); //&tm
        if (0 <= iResult) 
		{
			printf("iResult=%d \n", iResult);


			if (FD_ISSET(sockServer, &fdRead)) 
			{
				memset(&addrAccept,0,sizeof(addrTemp));
				sockAccept = accept(sockServer, (sockaddr *)&addrAccept, &iAcceptLen);
				if (INVALID_SOCKET != sockAccept) 
				{
					sAccept[iTemp] == INVALID_SOCKET; // 马上还要重新设置
					
					printf("%s:%d has connected server!\r\n", inet_ntoa(addrAccept.sin_addr),
						ntohs(addrAccept.sin_port));
                 }

				for( iTemp=0;iTemp<512;iTemp++)
				{
					if (sAccept[iTemp] == INVALID_SOCKET )
					{
						sAccept[iTemp] = sockAccept;
						break;
					}
				}
			}

		
            for(iTemp=0;iTemp<512;iTemp++) 
			{
			  if(sAccept[iTemp]!= INVALID_SOCKET)
			  {
                if (FD_ISSET(sAccept[iTemp], &fdRead)) 
				{
  
					{ //非服务器,接收数据(因为fd是读数据集)
                        memset(szDataBuff, 0, INT_DATABUFFER_SIZE);
                        iRecvSize = recv(sAccept[iTemp], szDataBuff, INT_DATABUFFER_SIZE, 0);

                        memset(&addrTemp, 0, sizeof(addrTemp));
                        iTempLen = sizeof(addrTemp);
                        getpeername(sAccept[iTemp], (sockaddr *)&addrTemp, &iTempLen);

                        // an error occurs
                        if (SOCKET_ERROR == iRecvSize) 
						{
                            closesocket(sAccept[iTemp]);
                            sAccept[iTemp] = INVALID_SOCKET;
                            i--;
                            printf("Failed to recv data ,%s:%d errorcode:%d.iTemp=%d\r\n",
                                inet_ntoa(addrTemp.sin_addr),ntohs(addrTemp.sin_port),WSAGetLastError(),iTemp);


                            continue;
                        }

                        // 客户socket关闭
                        if (0 == iRecvSize) 
						{
                            printf("%s:%d has closed iTemp=%d!\r\n",inet_ntoa(addrTemp.sin_addr),
                                ntohs(addrTemp.sin_port),iTemp);

                            closesocket(sAccept[iTemp]);

							sAccept[iTemp] = INVALID_SOCKET;
                            
                            i--;
                        }

                        // no error occurs, returns the number of bytes received
                        if (0 < iRecvSize) 
						{
                            printf("iTemp=%d recv %s:%d data:%s\r\n",iTemp, inet_ntoa(addrTemp.sin_addr),
                                ntohs(addrTemp.sin_port),szDataBuff);
                            char szEcho[2560] = {0};
                            sprintf(szEcho, "Server has got: %s.", szDataBuff);
                            send(sAccept[iTemp], szEcho, strlen(szEcho), 0);
                            closesocket(sAccept[iTemp]);
							sAccept[iTemp] = INVALID_SOCKET;
							
                        }
                    }
                }
			  }
            }
        }
		else if (SOCKET_ERROR == iResult) 
        {
            int iErr = WSAGetLastError();
            //WSACleanup();
            printf("Faild to select sockt in server!(Error: %d)\r\n", iErr);
            Sleep(100);
        }
    }
    WSACleanup();

    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值