select的使用方法記錄

服務端:

// select.cpp : 定義控制檯應用程序的入口點。
//

#include "stdafx.h"

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

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

#define INT_SERVER_PORT 6002
#define STR_SERVER_IP "127.0.0.1"
#define INT_DATABUFFER_SIZE 100

void main(void)
{
	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;
	}

	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;
	}
	
	/*
	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;
	}

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

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

	fd_set fd;
	FD_ZERO(&fd);
	FD_SET(sockServer,&fd);

	/*
	timeval tm;
	tm.tv_sec = 0;
	tm.tv_usec = 1000;
	*/
	printf("Start server.../r/n");
	while(1)
	{
		fd_set fdOld = fd;
		iResult = select(0,&fdOld,NULL,NULL,/*&tm*/NULL);
		if (0 <= iResult)
		{
			for(i = 0;i < fd.fd_count; i++)
			{
				if (FD_ISSET(fd.fd_array[i],&fdOld))
				{
					//如果socket是服務器,則接收連接
					if (fd.fd_array[i] == sockServer)
					{
						memset(&addrAccept,0,sizeof(addrTemp));
						sockAccept = accept(sockServer,(sockaddr *)&addrAccept,&iAcceptLen);
						if (INVALID_SOCKET != sockAccept)
						{
							FD_SET(sockAccept,&fd);
							//FD_SET(sockAccept,&fdOld);
							printf("%s:%d has connected server!/r/n",inet_ntoa(addrAccept.sin_addr),
								ntohs(addrAccept.sin_port));
						}
					}
					else //非服務器,接收數據(因爲fd是讀數據集)
					{
						memset(szDataBuff,0,INT_DATABUFFER_SIZE);
						iRecvSize = recv(fd.fd_array[i],szDataBuff,INT_DATABUFFER_SIZE,0);
						memset(&addrTemp,0,sizeof(addrTemp));
						iTempLen = sizeof(addrTemp);
						getpeername(fd.fd_array[i],(sockaddr *)&addrTemp,&iTempLen);
						
						if (SOCKET_ERROR == iRecvSize)
						{
							closesocket(fd.fd_array[i]);
							FD_CLR(fd.fd_array[i],&fd);
							i--;
							printf("Failed to recv data ,%s:%d errorcode:%d./r/n",
								inet_ntoa(addrTemp.sin_addr),ntohs(addrTemp.sin_port),WSAGetLastError());
							continue;
						}

						if (0 == iRecvSize)
						{
							//客戶socket關閉
							printf("%s:%d has closed!/r/n",inet_ntoa(addrTemp.sin_addr),
								ntohs(addrTemp.sin_port));
							
							closesocket(fd.fd_array[i]);
							FD_CLR(fd.fd_array[i],&fd);
							i--;	
						}
						
						if (0 < iRecvSize)
						{
							//打印接收的數據
							printf("recv %s:%d data:%s/r/n",inet_ntoa(addrTemp.sin_addr),
								ntohs(addrTemp.sin_port),szDataBuff);
						}
					}	
				}
			}
		}
		else if (SOCKET_ERROR == iResult)
		{
			//WSACleanup();	
		//	printf("Faild to select sockt in server!/r/n");
			Sleep(100);
		}
	}
	WSACleanup();
}



客戶端

// select-client.cpp : 定義控制檯應用程序的入口點。
//

#include "stdafx.h"

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

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

#define INT_SERVER_PORT 6002
#define STR_SERVER_IP "127.0.0.1"
#define INT_DATABUFFER_SIZE 100
#define STR_EXIT "exit"

void main(void)
{
	WSAData wsaData;
	WSAStartup(WINSOCK_VERSION,&wsaData);

	SOCKET sockClient = socket(AF_INET,SOCK_STREAM,0);
	if (INVALID_SOCKET == sockClient)
	{
		printf("Failed to create client!/r/n");
		WSACleanup();
	}

	sockaddr_in addrClient;
	addrClient.sin_addr.S_un.S_addr = inet_addr(STR_SERVER_IP);
	addrClient.sin_family = AF_INET;
	addrClient.sin_port = htons(INT_SERVER_PORT);


	int iResult;
	iResult = connect(sockClient,(sockaddr *)&addrClient,sizeof(sockaddr_in));
	if (SOCKET_ERROR == iResult)
	{
		printf("Failed to connect server!/r/n");
		WSACleanup();
		return;	
	} 

	if (0 != iResult)
	{
		int iErrorCode;
		iErrorCode = WSAGetLastError();
		printf("Failed to connect server,error:%d./r/n",iErrorCode);
		WSACleanup();
		return;
	}
	char szDataBuffer[INT_DATABUFFER_SIZE];
	while(1)
	{
		memset(szDataBuffer,0,INT_DATABUFFER_SIZE);
		scanf("%s",szDataBuffer);

		if (0 == strcmp(szDataBuffer,STR_EXIT))
		{
			printf("The client has stopped!/r/n");
			break;
		}
		else
		{
			if (1 > send(sockClient,szDataBuffer,strlen(szDataBuffer),0))
			{
				printf("Failed to send data!/r/n");
			}
		}
		Sleep(100);
	}
	closesocket(sockClient);
	WSACleanup();

}


原理記錄:

1、首先拷貝一份set, 使用select函數,沒有準備好的句柄會被刪除掉. 然後遍歷所有可用的句柄,並且處理。    

2、 如果socket爲服務器的socket,則是鏈接命令,使用accept

3、recv收到0,網絡關閉:closesocekt    -1 出錯                  0和-1都是網絡斷開

4、soceket建立都可以抓包:syn、ack,push,fin  在wareshake的抓包中


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章