您的位置:首页 > 理论基础 > 计算机网络

网络编程select

2013-09-24 21:56 344 查看
select模型实现了单线程上处理多个套接字的可能

1.select 函数定义如下

int select(

int nfds;

fd_set* readfds; //指向一个套接字集合

fd_set* writefds;

fd_set* exceptfds; //指向一个套接字集合,用来检查错误

const struct timeval* timeout //结构体 指定函数等待的最长时间 如果为NULL 则最长时间为无限长

);

2.套接字集合

fd_set结构可以把多个套接字连在一起,形成一个套接字集合。而select函数可以测试这个集合中哪些套接字有事件发生

typedef struct fd_set{

u_int fd_count;

SOCKET fd_array[FD_SETSIZE]; //套接字句柄数组 套接字集合 默认的是64

}fd_set;

3.操作fd_set的宏

FD_ZERO(*set) 很显然,初始化set为空集合,集合在使用前应该清空

FD_CLR(*set) 从set移除套接字s

FD_ISSET(s,*set) 检查s是不是set的成员,如果是返回TRUE

FD_SET(s,*set) 添加套接字到集合

主要程序代码:

#include"initsock.h"

#include<stdio.h>

CInitSock theSock; //初始化Winsock库

int main()

{

USHORT nPort=4567; //服务器监听的端口

//创建监听端口

SOCKET sListen=::socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

sockaddr_in sin;

sin.sin_family=AF_INET;

sin.sin_port=htons(nPort);

sin.sin_addr.S_un.S_addr=INADDR_ANY;

//绑定套接字到本地机器

if(::bind(sListen,(sockaddr*)&sin,sizeof(sin))==SOCKET_ERROR)

{

printf("Failed bind()");

return -1;

}

//进入监听模式

::listen(sListen,5);

//select模型处理过程

//第一步:初始化一个套接字 集合 fdSocket,添加监听套接字句柄到这个集合

fd_set fdSocket; //所有可用套接字集合

FD_ZERO(&fdSocket);

FD_SET(sListen,&fdSocket);

while(TRUE)

{

//第二步:将fdSocket集合的一个拷贝fdRead传递给select函数

//当有事件发生时,select函数移除fdRead集合中没有未决I/O操作的套接字句柄,然后返回

fd_set fdRead=fdSocket;

int nRet=::select(0,&fdRead,NULL,NULL,NULL);

if(nRet>0)

{

//第三步:通过将原来fdSocket集合与select处理过的fdRead集合比较

//确定有哪些套接字有未决I/O,并进一步处理这些I/O

for(int i=0;i<(int)fdSocket.fd_count;i++)

{

if(fdSocket.fd_array[i]==sListen) //监听套接字接收到新连接

{

if(fdSocket.fd_count<FD_SETSIZE)

{

sockaddr_in addrRemote;

int nAddrLen=sizeof(addrRemote);

SOCKET sNew=::accept(sListen,(SOCKADDR*)&addrRemote,&nAddrLen);

FD_SET(sNew,&fdSocket);

printf("接收到连接(%s)\n",::inet_ntoa(addrRemote.sin_addr));

}

else

{

printf("Too much connections!\n");

continue;

}

}

else

{

char szText[256];

int nRecv=::recv(fdSocket.fd_array[i],szText,strlen(szText),0);

if(nRecv>0)

{

szText[nRecv]='\0';

printf("接收到数据:%s\n",szText);

}

else

{

::closesocket(fdSocket.fd_array[i]);

FD_CLR(fdSocket.fd_array[i],&fdSocket);

}

}

}

}

else

{

printf("Failed select()\n");

break;

}

}

return 0;

}

其中 initsock

#include<WinSock.h>

#pragma comment(lib,"WS2_32")

class CInitSock

{

public:

CInitSock(BYTE minorVer=2,BYTE majorVer=2)

{

//初始化Wsh_32.dll

WSADATA wsaData;

WORD sockVersion=MAKEWORD(minorVer,majorVer);

if(::WSAStartup(sockVersion,&wsaData)!=0)

{

exit(0);

}

}

~CInitSock()

{

::WSACleanup();

}

};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: