您的位置:首页 > 其它

Socket WSAAsyncSelect模型值得注意的一个地方

2011-01-14 18:47 190 查看
参考Programming Windows TCP Sockets in C++ for the Beginners(见codeproject), socket I/O模型选择WSAAsyncSelect进行编程时,参考代码有个bug:Server端第一次连接并读取Client端发送的buffer OK, 第二次就没有FD_READ事件了。



问题相关代码

WSAAsyncSelect (s, hwnd, 1045, FD_READ | FD_CONNECT | FD_CLOSE | FD_ACCEPT);



case FD_CLOSE: //Lost connection
    MessageBeep(MB_ICONERROR);
    
    //Clean up
    if (s) closesocket(s);
    WSACleanup();
    
    SendMessage(hStatus, SB_SETTEXT, 0, (LPARAM)"Connection to Remote 
break;
case FD_READ: //Incoming data to receive
    char buffer[80];
    memset(buffer, 0, sizeof(buffer)); //Clear the buffer
    
    recv (s, buffer, sizeof(buffer)-1, 0); //Get the text
    
    GetTextandAddLine(buffer, hwnd, ID_EDIT_DATA); //Display it
break;
case FD_ACCEPT: //Connection request
{
    MessageBeep(MB_OK);
    
    SOCKET TempSock = accept(s, (struct sockaddr*)&from, &fromlen);
    s = TempSock; //Switch our old socket to the new one
    
    char szAcceptAddr[100];
    wsprintf(szAcceptAddr, "Connection from [%s] accepted.",
      inet_ntoa(from.sin_addr)); 
      
    SendMessage(hStatus, SB_SETTEXT, 0, 
      (LPARAM)szAcceptAddr);
}
break;




s(套接字)为全局变量。以上代码可以看到accept客户端连接替换的套接字与WSAAsyncSelect模型事件通知的套接字同一变量。



看看事件顺序

第一次客户端连接并发送buffer

FD_ACCEPT WSAAsyncSelect模型事件通知的套接字替换为accept客户端连接替换的套接字

FD_READ 从accept客户端连接替换的套接字读取buffer

FD_CLOSE 关闭客户端与Server的socket连接



第二次客户端连接并发送buffer

FD_ACCEPT 此时WSAAsyncSelect模型事件通知的套接字已经非法,使用accept从WSAAsyncSelect模型事件通知的套接字获取客户端连接套接字显示失败。



所以我们需要区分客户端连接替换的套接字与WSAAsyncSelect模型事件通知的套接字。



解决方案如下:

1、定义两个socket全局变量

SOCKET s; //WSAAsyncSelect模型事件通知的套接字同一变量

SOCKET c; //accept客户端连接替换的套接字





case FD_CLOSE: //Lost connection

if (c) closesocket(c);

break;







case FD_READ: //Incoming data to receive

static char buffer[80];

memset(buffer, 0, sizeof(buffer)); //Clear the buffer

recv (c, buffer, sizeof(buffer)-1, 0); //Get the text

break;







case FD_ACCEPT: //Connection request

{

char szAcceptAddr[100];

SOCKET TempSock = accept(s, (struct sockaddr*)&from, &fromlen);

c= TempSock; //Switch our old socket to the new one

break;

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