关于select模型
winsock编程,采用select实现面向连接一个服务器和多个客户端的收发数据,运行时产生错误,劳驾帮忙看一下:
#include<iostream.h>
#include<winsock2.h>
#define DEFAULT_PORT 4000
void WINAPI SendOut();
char info[255];
bool isConnect;
SOCKET sServSock= socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
fd_set fds;
void main()
{
WORD wVersionRequested=MAKEWORD(2,2); //初始化winsock
WSADATA wsaData;
WSAStartup(wVersionRequested,&wsaData);
//SOCKET sServSock= socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
sockaddr_in addr;
int nSockErr;
int nNumConns=0;
SOCKET sClient;
sockaddr ConnAddr;
int nAddrLen=sizeof(sockaddr);
addr.sin_family=AF_INET;
addr.sin_port =htons(DEFAULT_PORT);
addr.sin_addr.s_addr=htonl(INADDR_ANY);
if(bind(sServSock,(LPSOCKADDR)&addr,sizeof(addr))==SOCKET_ERROR) //SOCKET_ERROR=-1
{
nSockErr=WSAGetLastError();
}
if(listen(sServSock,5)==SOCKET_ERROR)
{
nSockErr=WSAGetLastError();
}
//fd_set fds;
FD_ZERO(&fds);
FD_SET(sServSock,&fds);
CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)SendOut,NULL,0,NULL); //发送数据
bool bRunning=1;
do{
fd_set readfds;
CopyMemory(&readfds,&fds,sizeof(fd_set));
if(select(0,&readfds,NULL,NULL,NULL)>0)
{
for(int i=readfds.fd_count-1;i>=0;i--)//顺序处理每一个有事件发生的套接字
{
if(readfds.fd_array[i]=sServSock)
{
sClient=accept(sServSock,&ConnAddr,&nAddrLen);
if(sClient==INVALID_SOCKET){
bRunning=false;
break;
}
cout<<"Client Accept Successfull."<<endl;
FD_SET(sClient,&fds); //将与新客户端对应的套接字加入select函数监视的集合
}
else//与客户端对应的套接字有事件发生说明有数据需要接收
{
char in[255];
sClient=readfds.fd_array[i];
if(recv(sClient,in,255,0)!=SOCKET_ERROR)
cout<<"\b<"<<in<<endl<<">";
else{
cout<<"\b<"<<"client exit"<<endl<<">";
FD_CLR(sClient,&fds); //将该套接字移出select集合
closesocket(sClient);
}
}
}
}
}while(bRunning);
WSACleanup();
}
void WINAPI SendOut()
{
do
{
cin.getline(info,255);
if(!strcmp(info,"bye"))break;
cout<<">";
for(int i=fds.fd_count-1;i>=0;i--)
{
if(fds.fd_array[i]!=sServSock)
{
fd_set writefds;
FD_ZERO (&writefds);
FD_SET(fds.fd_array[i],&writefds);
if(select(0,NULL,&writefds,NULL,NULL)>0)
send(fds.fd_array[i],info,255,0);
}
}
}while(true);
closesocket(sServSock);
}