您的位置:首页 > 其它

select的使用方法记录

2014-07-07 14:41 190 查看
服务端:

// 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的抓包中
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: