王骏的BLOG
编程、网络技术点滴...
<2005年6月>
2930311234
567891011
12131415161718
19202122232425
262728293012
3456789
公告

留言簿(24)

随笔分类

随笔档案

文章分类

文章档案

相册

WEB开发

相关链接

搜索

最新评论

阅读排行榜

评论排行榜

 
VC知识库BLOG   首页  新随笔  联系  聚合  登录 
  随笔-61 文章-5 评论-247 Trackbacks-0
阻塞模式下当完成数据的发送后,关闭套节字不能用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

posted on 2005-06-25 13:48 王骏的BLOG 阅读(2170) 评论(8)  编辑 收藏
Comments
  • # re: 阻塞模式下套接字的安全关闭
    freedk
    Posted @ 2005-06-25 16:46
    在socket中看到过用shutdown的方法,当时不知道有啥用。。唉,只怪太浮了。。
  • # re: 套接字的雅致断连(graceful disconnect)
    周星星
    Posted @ 2005-06-26 11:49
    好东西,可惜没早看到。
  • # re: 套接字的雅致断连(graceful disconnect)
    乾坤一笑
    Posted @ 2005-06-26 14:22
    to 周星星:《TCP/IP详解 卷1:协议》写的很详细,看来你又没看过。:)
  • # re: 套接字的雅致断连(graceful disconnect)
    周星星
    Posted @ 2005-06-26 14:26
    《TCP/IP详解》,我记下了,不过为什么好书这么多呀,我实在没时间看呀。
  • # 不解哩
    诺亚
    Posted @ 2005-06-26 14:36
    阻塞模式下, 数据发送函数返回时. 就已经确保数据已经到接收方的缓冲区了.
    接收方可以读取这些数据, 怎么会造成数据的丢失呢?


    别怪说我傻呵  > <~~~
  • # 好像一般称为完美关闭吧。
    Diviner
    Posted @ 2005-06-26 15:46
    rt
  • # 来了几次了
    清风雨
    Posted @ 2005-06-27 14:16
    1.shutdown告诉系统停止socket的某项服务(SD_BOTH是收发都停止服务)
    2.closesocket关闭socket句柄
  • # re: 套接字的雅致断连(graceful disconnect)
    wangjun
    Posted @ 2005-06-27 21:54
    数据发送函数返回时. 只能保证数据已经发送方的缓冲区,除非发送方系统缓冲设为0才表示数据已经上路了。
标题  
姓名  
主页
验证码 *
内容   
  登录  使用高级评论  Top
[使用Ctrl+Enter键可以直接提交]