阻塞模式下,服务器端send发送数据给客户端后,马上关闭与之连接的套接字closesocket,会不会影响客户端接收?
比如下面的代码
服务器端依次调用 
bind(listenSock,...
listen(listenSock,... 
SOCKET clientSocket=accept(listenSock,...);
send(clientSocket,......);
closesocket(clientSocket);如果服务器端发送后,客户端马上就能接收到,那没问题。但如果客户端接收之前,服务器端就已经关闭了与之相连的套接字clientSocket,客户端还能收到吗?

解决方案 »

  1.   

    那就要分两种情况了,tcp和udp方式了,tcp为面向连接的协议,而udp是无面向连接的,例如qq就是udp协议的,tcp不能收到,但udp不一定收不到.
      

  2.   

    如果客户端接收之前,服务器端就已经关闭了与之相连的套接字clientSocket,客户端还能收到吗? 
    ------------------------------------------------
    客户端接收得到,因为数据已经发到网线上了。而在这之后服务端调用closesocket之后,客户端调用recv方法会返回-1,表示服务端已断开。
      

  3.   

    tcp方式的,另: 我在自己机器上做了下测试,服务器和客户端程序都在我机器上运行
    客户端程序依次调用
    connect
    Sleep(10000);
    recv按理服务器端send后就马上closesocket了,客户端sleep后(确保服务器端先关闭套接字)再接收,应该是收不到,但事实上却收到了?
      

  4.   

    连着两次调用recv,其中第一个recv接收到数据,第二个recv返回0,呵呵
      

  5.   

    异步方式下,
    s端 send以后,就可以关了。不会影响c端接收。
    至于c端是否能够实际接收到,只与网络状况,以及c端算法有关了
      

  6.   

    同步方式下, send是等接收完才返回的。所以client端sleep也没有用的,server在等recv后才返回吧。
      

  7.   

    异步方式下要保证SO_LINGER的设置~ 只有shutdown gracefully才能保证对端能收到。
      

  8.   

    主要看协议是否已经把数据发出了,至于recv和send都只是把数据复制到缓存区而已
      

  9.   

    我理解底层是这样实现的
    server.send() -> 数据放入发送缓冲 -> 通过网络到达client的接收缓冲
    client.recv() -> 从接收缓冲区取出
    如果是这样的,那么send后closesocket也晚了,数据已经到达(如果是tcp的话)
      

  10.   

    从MSDN的closesocket说明中摘一段话:Here is a summary of closesocket behavior:If SO_DONTLINGER is enabled (the default setting) it always returns immediately???connection is gracefully closed in the background. 
    If SO_LINGER is enabled with a zero time-out:
    – it always returns immediately — connection is reset/terminated.If SO_LINGER is enabled with a nonzero time-out:
    – with a blocking socket, it blocks until all data sent or time-out expires.– with a nonblocking socket, it returns immediately indicating failure.
      

  11.   

    是否收到取决于send的返回值。
      

  12.   

    如果该包可以顺利到达(比如没发生延时或者TTL为0)是可以接收得到的。也就是13楼说的SEND返回值思路可以这样想:假设包已发出去了,那肯定是不关发送端的事了。完全是路由在控制。如果是TCP的话,只是在等待一个是否到达的值。如果非要说不可到达的话,那要解决的问题是怎么追包回来? 
    我想到的方法是发送个丢包的指令。
    但是已发送包的这个路由怎么记录?你指令怎么追踪到他的路由?。。所以说这个追包就已经实现不了了
      

  13.   

    要看实际情况,以及编程模式.如果是阻塞的socket,send()发送成功后,用closesocket(),有可能收到,也有可能收不到.如果socket被设置了
    struct linger Lin;
     Lin.l_onoff = 0;
     Lin.l_linger = 0;
     setsockopt(TheSocket, SOL_SOCKET, SO_LINGER, (char *)&Lin,sizeof(Lin));那么多数是收不到.但如果没设置,只是默认下,很大可能可以收到.非阻塞模式的话,那么很大程度依赖网络情况了.如果还是重叠IO的socket发送,更要看系统当前缓冲是否足够在closesocket()前数据已被调入系统底层去.结论:这个问题没有一个绝对的答案,在不同编程模式,不同的网络环境,都可能得到不同的结果.就算是相同的编程模式,相同的网络环境,连续测试10来次,得到的结果也不相同.
      

  14.   

    同意樓上的。struct linger Lin; 
     Lin.l_onoff = 0; 
     Lin.l_linger = 0; 
     setsockopt(TheSocket, SOL_SOCKET, SO_LINGER, (char *)&Lin,sizeof(Lin)); 
    關閉前先 shutdown, 再 closesocket直接 closesocket 對方會收不到
      

  15.   

    首先保证网络环境至少要正常,如果网络环境很差,那就不好说了 。
    一般仅仅调用CLOSESOCKET,不会影响发送的数据,除非你刻意设置强制关闭,才有影响。
      

  16.   

     huang_yu_qiang 
     
    等级:
     发表于:2008-03-09 22:44:3111楼 得分:0 
    我理解底层是这样实现的 
    server.send() ->  数据放入发送缓冲 ->  通过网络到达client的接收缓冲 
    client.recv() ->  从接收缓冲区取出 
    如果是这样的,那么send后closesocket也晚了,数据已经到达(如果是tcp的话) 
    ===========================================================
    这个应该是对的.