一看二做三总结
分类: LINUX
2010-09-24 20:36:57
//加载winsock库
if (WSAStartup(MAKEWORD(2,2),&wsadata)!=0)
{
int error1 = WSAGetLastError();
CString error_str1;
error_str1.Format("%d",error1);
error_str1 = "加载winsock库失败,错误代码:"+error_str1;
AfxMessageBox(error_str1);
return 1;
}
connectsock = socket(AF_INET,SOCK_STREAM,0);//创建套接字
if (connectsock==INVALID_SOCKET)
{
int error2 = WSAGetLastError();
CString error_str2;
error_str2.Format("%d",error2);
error_str2 = "套接字创建失败,错误代码:"+error_str2;
AfxMessageBox(error_str2);
return 1;
}
sockaddr_in ser;
ser.sin_family = AF_INET;
ser.sin_port = htons(5001);
ser.sin_addr.s_addr = inet_addr(netipstr);
//请求与服务器建立连接
if(connect(connectsock,(struct sockaddr*)&ser,sizeof(ser))==SOCKET_ERROR){
int error3 = WSAGetLastError();
CString error_str3;
error_str3.Format("%d",error3);
error_str3 = "连接对方主机失败,错误代码:"+error_str3;
AfxMessageBox(error_str3);
return 1;
}
memset(recvbuf,0,sizeof(recvbuf));
FD_ZERO(&fdread);
FD_SET(connectsock,&fdread);
tv.tv_sec = 1;//设置延迟为1秒
tv.tv_usec = 0;
while(1){
int iselect = select(0,&fdread,NULL,NULL,&tv);
if(iselect<0){
int error4 = WSAGetLastError();
CString error_str4;
error_str4.Format("%d",error4);
error_str4 = "select发生错误,错误代码:"+error_str4;
AfxMessageBox(error_str4);
return 1;
}
if(FD_ISSET(connectsock,&fdread)){//检查套接字connectsock是否在结合fdread中,即检查是否有数据到来
memset(recvbuf,0,sizeof(recvbuf));
lenrecv = recv(connectsock,recvbuf,sizeof(recvbuf),0);
//数据处理省略
}else{//数据未到
//数据处理省略
}
}
这个程序,已经把妨碍分析的程序略去,经过测试,第一次select检查的时候没有报错,而第二次检查的时候就报了10022错误,那出错的原因是什么呢?我先来解释一下select函数的作用。
select函数:如果程序要检查套接字上是否有数据到来,则首先需要把套接字句柄加入可读性监视集合中,然后调用select,如果该套接字没有数据需要接收,则select函数会把该套接字从可读性监视集合中删除,所以,程序只要检查该套接字句柄是否还在可读性监视集合中,就可以判断出是否有数据需要接收。
这下我们明白了为什么了吧,原因就是因为我们第一次调用select函数的时候,没有数据到来,select函数将套接字从可读性监视集合中删除,而我们第二次调用select函数的时候,系统认为你提供了非法参数,所以会报10022错误。
解决办法就是在每次调用select之前必须加入如下代码:
FD_ZERO(&fdread);
FD_SET(connectsock,&fdread);
tv.tv_sec = 1;//设置延迟为1秒
tv.tv_usec = 0;
修改后的程序:
//加载winsock库
if (WSAStartup(MAKEWORD(2,2),&wsadata)!=0)
{
int error1 = WSAGetLastError();
CString error_str1;
error_str1.Format("%d",error1);
error_str1 = "加载winsock库失败,错误代码:"+error_str1;
AfxMessageBox(error_str1);
return 1;
}
connectsock = socket(AF_INET,SOCK_STREAM,0);//创建套接字
if (connectsock==INVALID_SOCKET)
{
int error2 = WSAGetLastError();
CString error_str2;
error_str2.Format("%d",error2);
error_str2 = "套接字创建失败,错误代码:"+error_str2;
AfxMessageBox(error_str2);
return 1;
}
sockaddr_in ser;
ser.sin_family = AF_INET;
ser.sin_port = htons(5001);
ser.sin_addr.s_addr = inet_addr(netipstr);
//请求与服务器建立连接
if(connect(connectsock,(struct sockaddr*)&ser,sizeof(ser))==SOCKET_ERROR){
int error3 = WSAGetLastError();
CString error_str3;
error_str3.Format("%d",error3);
error_str3 = "连接对方主机失败,错误代码:"+error_str3;
AfxMessageBox(error_str3);
return 1;
}
memset(recvbuf,0,sizeof(recvbuf));
while(1){
FD_ZERO(&fdread);
FD_SET(connectsock,&fdread);
tv.tv_sec = 1;//设置延迟为1秒
tv.tv_usec = 0;
int iselect = select(0,&fdread,NULL,NULL,&tv);
if(iselect<0){
int error4 = WSAGetLastError();
CString error_str4;
error_str4.Format("%d",error4);
error_str4 = "select发生错误,错误代码:"+error_str4;
AfxMessageBox(error_str4);
return 1;
}
if(FD_ISSET(connectsock,&fdread)){//检查套接字connectsock是否在结合fdread中,即检查是否有数据到来
memset(recvbuf,0,sizeof(recvbuf));
lenrecv = recv(connectsock,recvbuf,sizeof(recvbuf),0);
//数据处理省略
}else{//数据未到
//数据处理省略
}
}