王骏的博客
编程、网络技术点滴...

公告

逐渐将VC知识库的博客迁移到这里!

随笔分类

随笔档案

相册

最新评论

阅读排行榜

评论排行榜

程序员博客   首页  新随笔  订阅  管理  登录 
 
王骏的博客 阅读(1874) 评论(8)
阻塞模式下当完成数据的发送后,关闭套节字不能用closesocket一关了之,这样会造成数据的丢失。
正确的做法是调用shutdown,发送SD_SEND参数进行"半关闭", 这样做TCP会在数据发送完成后发送FIN通知对方,然后循环用recv接收直到对方关闭套接字发送过来FIN。参考代码如下:

void CloseSocket(SOCKET hSocket)
{
    
if(hSocket == INVALID_SOCKET)
        
return;

    
// 半关闭
    if(shutdown(hSocket, SD_SEND) != SOCKET_ERROR)
    
{
        
char buf[1024];
    
int nRecv = 0;
    
do
    
{
        nRecv 
= recv(m_hSocket, buf, 10240);
    }
 while (!(nRecv == 0 || nRecv == SOCKET_ERROR));
    }

    
    
// 关闭
    closesocket(hSocket);
}


对于WINDOWS,可以配合WSAAsyncSelect选择FD_CLOSE事件,参考代码:

void CloseSocket(SOCKET hSocket)
{
    
if(hSocket == INVALID_SOCKET)
        
return;
    
    WSAEVENT hEvent 
= WSA_INVALID_EVENT; 
    
    
for(;;)
    
{
        hEvent 
= WSACreateEvent();
        
if(hEvent == WSA_INVALID_EVENT) 
            
break;

        
if(WSAEventSelect(hSocket, hEvent, FD_CLOSE) != 0
            
break;

        
if(shutdown(hSocket, SD_SEND) != 0
            
break;

        
if(WaitForSingleObject(hEvent, 200!= WAIT_OBJECT_0)
            
break;

        
char buf[1024];
        
int nRecv = 0;
        
do
        
{
            nRecv 
= recv(hSocket, buf, 10240);
        }
 while (!(nRecv == 0 || nRecv == SOCKET_ERROR));

        
break;
    }


    
if (hEvent != WSA_INVALID_EVENT) 
    
{
        WSACloseEvent(hEvent); 
        hEvent 
= WSA_INVALID_EVENT; 
    }

    
    closesocket(hSocket);
}


关于半关闭的描述请参考《TCP/IP详解 卷1:协议》

参考链接

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/shutdown_2.asp
http://tangentsoft.net/wskfaq/examples/basics/ws-util.cpp
http://www.flipcode.com/articles/network_part02.shtml
http://www.codeguru.com/forum/archive/index.php/t-288238.html


评论列表
freedk
re: 阻塞模式下套接字的安全关闭
在socket中看到过用shutdown的方法,当时不知道有啥用。。唉,只怪太浮了。。
周星星
re: 套接字的雅致断连(graceful disconnect)
好东西,可惜没早看到。
乾坤一笑
re: 套接字的雅致断连(graceful disconnect)
to 周星星:《TCP/IP详解 卷1:协议》写的很详细,看来你又没看过。:)
周星星
re: 套接字的雅致断连(graceful disconnect)
《TCP/IP详解》,我记下了,不过为什么好书这么多呀,我实在没时间看呀。
诺亚
不解哩
阻塞模式下, 数据发送函数返回时. 就已经确保数据已经到接收方的缓冲区了.
接收方可以读取这些数据, 怎么会造成数据的丢失呢?


别怪说我傻呵  > <~~~
清风雨
来了几次了
1.shutdown告诉系统停止socket的某项服务(SD_BOTH是收发都停止服务)
2.closesocket关闭socket句柄
wangjun
re: 套接字的雅致断连(graceful disconnect)
数据发送函数返回时. 只能保证数据已经发送方的缓冲区,除非发送方系统缓冲设为0才表示数据已经上路了。

发表评论
切换编辑模式