代码之家  ›  专栏  ›  技术社区  ›  Hosam Aly

如何检查(TCP)套接字是否在C_中连接(dis)?

  •  33
  • Hosam Aly  · 技术社区  · 17 年前

    我应该如何检查(TCP)套接字以确定它是否已连接?

    我读过关于 Socket.Connected 属性 MSDN ,但它说它只根据上一个I/O显示状态。这对我不有用,因为我想这样做 之前 正在尝试从套接字读取。备注部分还注意到:

    如果你需要确定电流 连接状态,使 非阻塞,零字节发送调用。如果 呼叫成功返回,或者 引发WaewouldBlock错误代码 (10035),则插座仍在 已连接;否则,套接字为“否” 更长的连接时间。

    同一页上的示例显示了如何执行此操作。 (1) 但是 a post by Ian Griffiths 说我应该 阅读 从插座,不是 发送 通过它。

    Another post by Pete Duniho 说:

    …你打电话之后 Shutdown() , 呼叫 Receive() 直到它回来 0 (假设远程端点不是 实际上会给你寄任何东西, 一旦遥控器 终结点已接收所有 数据)。除非你这样做,否则你 无法保证远程终结点 已经收到所有数据 你发送了,甚至使用了一个挥之不去的 插座。

    我不太明白他关于打电话的说法 接收() 以确保远程端点实际接收到 发送 . (在发送缓冲区为空之前套接字是否阻止接收?)

    我对提出的不同方法感到困惑。你能解释一下吗?


    (1)我想知道为什么 example 对于 插座。已连接 属性分配一个1字节数组,即使它调用 Send 长度0?

    4 回复  |  直到 13 年前
        1
  •  21
  •   Quassnoi    17 年前

    套接字的死亡会以多种方式改变其行为,因此这些方法都是有效的:)

    使用这两种方法,您实际上可以检查在断开连接后发生变化的套接字行为的那些部分。

    我真的不理解他关于调用receive()以确保远程端点实际接收了我发送的所有数据的声明。(在发送缓冲区为空之前套接字是否阻止接收?)

    TCP 是可靠的协议,这意味着你发送的每个包都必须被确认。确认意味着用 ACK 位集。这些数据包可能包含或不包含附加(有效负载)数据。

    当插座连接时, Receive() 将一直阻塞,直到套接字接收到具有非空有效负载的数据包。但是当插座断开时, 接收() 会尽快回来的 ACK 数据包到达。

    打电话 接收() 确保你 接收 那最后 ACK 来自远程端点的数据包或发生断开连接超时,您将能够 接收 这个插座上没有其他东西了。

    同一页上的示例显示了如何执行此操作。(我想知道为什么它要分配一个1字节数组,即使它调用的发送长度为0?)但是伊恩·格里菲斯的一篇文章说我应该从插座上阅读,而不是通过插座发送。

    什么时候? send() 对于一个套接字,您实际上尝试将一些数据附加到套接字队列的末尾。缓冲区还有什么地方吗,然后你的 Send() 如果没有,立即返回 Sead() 一直到有地方。

    当插座处于断开状态时, TCP/IP 堆栈防止缓冲区的所有进一步操作,这就是为什么 Sead() 返回一个错误。

    Sead() 实现基本指针检查,这意味着当 NULL 指针被传递给它。您可能会将任何非空常量作为指针传递,但为了以防万一,您最好分配1个字节,而不是将该常量变为“空”。


    您可以使用任何您喜欢的方法,因为它们都不消耗资源。只要它们用于插座连接检查,它们是相同的。

    至于我,我更喜欢 接收() ,因为这是您通常在一个循环中运行并等待的。你得到一个非零的 接收() ,处理数据;得到零,处理断开。

        2
  •  4
  •   Svish    15 年前

    “如果需要确定连接的当前状态,请进行一个非阻塞的零字节发送调用。如果调用成功返回或抛出一个waewouldBlock错误代码(10035),那么套接字仍处于连接状态;否则,套接字将不再连接。“——不幸的是,它甚至无法工作!

    mySocket.Blocking = false;
    byte[] buffer = new byte[1];
    int iSent = mySocket.Send(buffer, 0, SocketFlags.None);
    bConnected = mySocket.Connected;
    

    bConnected始终以true结束,即使已拔下以太网电缆,呼叫也始终成功返回。

    而且,不幸的是,==发送任何实际数据也不会检测到断开的连接。

    buffer[0] = 0xff ;
    int iSent = mySocket.Send(buffer, 1, SocketFlags.None);
    

    重复返回1,就好像真的发送了什么。而问题设备甚至不再连接。

        3
  •  1
  •   ng5000    17 年前

    通常会使用socket.select方法来确定一组套接字的状态(socket.poll用于单个套接字)。

    这两种方法都允许您查询套接字的状态。现在,假设您已经跟踪了第一个连接的套接字,那么您通常会在尝试读取之前调用套接字上的select/poll。如果select/poll指示套接字可读,则说明:

    • 要么套接字有可用的数据顶读,在这种情况下,receive将返回可用的数据。
    • 套接字已关闭,在这种情况下,当您调用receive时,将立即返回0字节(即,如果select/poll指示套接字可读,而您调用receive,但它立即返回0字节,则您知道连接已关闭、重置或终止。

    就我个人而言,我从来没有使用过poll——我一直使用select,但msdn似乎建议,poll与select几乎相同,只是用于单套接字。

    我还要补充一点,在大多数情况下,使用select是处理套接字连接的最有效和最好的方法。

        4
  •  1
  •   user207421    13 年前

    我真的不理解他关于调用receive()以确保远程端点实际接收了我发送的所有数据的声明。

    @peteduniho的帖子不是关于建立连接状态的,而是关于以一种您知道对等端何时接收到您的所有数据的方式终止连接。

    (在发送缓冲区为空之前套接字是否阻止接收?)

    不,但是如果您关闭套接字,然后读取到EOS,那么您将等待对等机读取所有数据,直到 获取eos,然后关闭套接字。因此,您可以保证所有数据都已进入对等应用程序。

    推荐文章