2010年6月21日14:22:51
在window下socket编程
使用select的时候与linux下有些不同:
=============转载一段先=======================
1.select模型
int select(int nfds, // 忽略,为了与Berkeley兼容
fd_set FAR* readfds, // 1.1
fd_set FAR* writefds, // 1.2
fd_set FAR* exceptfds, // 1.3
const struct timeval FAR* timeout); // 1.4
1.1 readfds集合包括符合下述任何一个条件的套接字:
#有数据可以读入
#连接已经关闭,重设或终止
#加入已调用了listen,而且一个连接正在建立,那么accept函数调用会成功
1.2 writefdss集合包括符合下述任何一个条件的套接字:
#有数据可以发出
#如果已完成了对一个非锁定连接调用的处理,连接就会成功
1.3 exceptfdss集合包括符合下述任何一个条件的套接字:
#假如已完成了对一个非锁定连接调用的处理,连接尝试就会失败.
#有带外(Out-of-band, OOB)数据可用读取
** 这三个参数中任意两个可以为空,但不能都为空,否则select没有等待任何数据.
1.4 struct timeval
struct timeval
{
long tv_sec; // (单位:秒)
long tv_usec; // (单位:毫秒)
}
** select()函数返回设置的监听socket发生操作,返回操作个数
e.g. int ret = select(0, &fdread, NULL, NULL, &tv);
当监视的socket发生读操作时,ret返回列队中的个数,于是产生后续的操作
** 个人绝对select就是为了accept函数能够立即返回,不会造成系统卡在一个函数上,导致挂起的样子,但是cpu使用率会飙升,那还不如就直接用accept,至少cpu占用率不会飙升(在没有连接到来的时候)
===========================
fd中保存的socket是不能直接使用的,必须额外设置一个数组保存socket,在每次select完之后,需要重新将数组中的socket FD_SET到fd中(我不清楚为什么,反正如果不这样的话select会出问题)。
附上自己写的一段代码
=================
int initWinSock()
{
WSADATA wsaData;
WORD wVersionRequested=MAKEWORD(1,1);
if( 0 == WSAStartup (wVersionRequested, &wsaData))
{
cout<<"RUN-MSG:Sucess to connect to the lib of socket!"<<endl;
return 0;
}
else
{
cout<<"ERR-MSG:Failed to connect to the lib of socket!"<<endl;
return -1;
}
//wVersionRequested是我们要求使用的WinSock的版本。
}
void* ServerThread(void* para)
{
}
int main(int argc, char *argv[])
{
#ifdef _WIN32
cout<<"win32!"<<endl;
if(0 != initWinSock())
return -1;
#else
cout<<"Linux!"<<endl;
#endif
int sock, client_sock;
int sock_arr[64];
static int s_num_socket = 0;
short sport = 8989;
string sip = "127.0.0.1";
if(argc == 2)
sport = atoi(argv[1]);
if(argc == 3)
{
sport = atoi(argv[1]);
sip = argv[2];
}
cout<<"ip is "<<sip<<", port is "<<sport<<endl;
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct sockaddr_in sockaddr, client_addr;
fd_set fd, newfd;
int error_code;
int len ,l;
string strread = "";
// sockaddr.sin_family = AF_INET;
// sockaddr.sin_port = htons(sport);
// sockaddr.sin_addr.s_addr = inet_addr(INADDR_ANY);
sockaddr.sin_family = AF_INET;
sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); //inet_addr("127.0.0.1");//0;//;//inet_addr(INADDR_ANY);
sockaddr.sin_port = htons(sport);
if((SOCKET_ERROR == bind(sock,(struct sockaddr *)&sockaddr, sizeof(struct sockaddr_in))) )
{
cout<<"ERR-MSG:bind error! :"<<error_code<<endl;
cout<<WSAGetLastError()<<endl;
system("PAUSE");
return -2;
}
else
cout<<"RUN-MSG:bind sucess!"<<endl;
if(SOCKET_ERROR == (error_code = listen(sock, 20)) )
{
cout<<"ERR-MSG:listen error! :"<<error_code<<endl;
system("PAUSE");
return -3;
}
else
cout<<"RUN-MSG:listen success!the port is:"<<sport<<endl;
u_long mode = 1;
ioctlsocket(sock,FIONBIO,&mode);
// ioctlsocket(sock, FIONBIO,(u_long FAR*) &mode);//设置非阻塞的socket
char opt = 1;
// setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
FD_ZERO(&fd);
FD_SET(sock, &fd);
sock_arr[s_num_socket++] = sock;
char buffer[256];
memset(buffer, 0, 256);
len = sizeof(struct sockaddr_in);
int i;
newfd = fd;
while(1)
{
int ret = select(0, &newfd, NULL, NULL, NULL);
if(ret < 0)
{
cout<<"ERR-MSG:select error!"<<endl;
system("PAUSE");
return -1;
}
for(i=0; i<s_num_socket; i++)
{
if(FD_ISSET(sock_arr[i], &newfd))
{
cout<<"i is"<<i<<endl;
if(sock_arr[i] == sock)
{
cout<<"RUN-MSG:it's me!"<<endl;
if((client_sock = accept(sock, (struct sockaddr*)&client_addr ,&len)) != INVALID_SOCKET)
{
cout<<"RUM-MSG:a new client!"<<endl;
FD_SET(client_sock, &newfd);
sock_arr[s_num_socket++] = client_sock;
memset(buffer, 0, 256);
}
}
else
{
int ret = recv(sock_arr[i], buffer, 256, 0);
if(ret > 1)
cout<<buffer<<endl;
else
{
if (WSAGetLastError() == WSAECONNRESET)
{
// Client socket closed
cout<<"RUN-MSG:Client socket "<<sock_arr[i]<<"has close"<<endl;
if(sock_arr[i] != INVALID_SOCKET)
{
FD_CLR(sock_arr[i], &newfd);
close(sock_arr[i]);
}
cout<<"RUN-MSG:Remove client socket!"<<sock_arr[i]<<" success!"<<endl;
sock_arr[i--] = sock_arr[--s_num_socket];
} //坏连接
}//坏连接的情况
}
}
}
FD_ZERO(&newfd);
//重新置newfd状态;
for(i=0; i<s_num_socket; i++)
FD_SET(sock_arr[i],&newfd);
sleep(1);
close_sock(sock);
WSACleanup();
system("PAUSE");
return EXIT_SUCCESS;
}