有没有办法检测 TCP 套接字已被远程对等方关闭,而无需从中读取? [英] Is there a way to detect that TCP socket has been closed by the remote peer, without reading from it?

查看:24
本文介绍了有没有办法检测 TCP 套接字已被远程对等方关闭,而无需从中读取?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,解释一下动机的一些背景知识:我正在研究一个非常简单的基于 select() 的 TCP镜像代理",它允许两个受防火墙保护的客户端相互间接通信.两个客户端都连接到该服务器,一旦两个客户端都连接,客户端 A 发送到服务器的任何 TCP 字节都会转发到客户端 B,反之亦然.

First, a little background to explain the motivation: I'm working on a very simple select()-based TCP "mirror proxy", that allows two firewalled clients to talk to each other indirectly. Both clients connect to this server, and as soon as both clients are connected, any TCP bytes sent to the server by client A is forwarded to client B, and vice-versa.

这或多或少有效,但有一个小问题:如果客户端 A 连接到服务器并在客户端 B 连接之前开始发送数据,则服务器没有任何地方可以放置数据.我不想将它缓存在 RAM 中,因为这最终可能会使用大量 RAM;而且我也不想删除数据,因为客户端 B 可能需要它.所以我选择第三个选项,即在客户端 B 也连接之前不在客户端 A 的套接字上选择()-for-read-ready.这样客户端 A 就会一直阻塞,直到一切准备就绪.

This more or less works, with one slight gotcha: if client A connects to the server and starts sending data before client B has connected, the server doesn't have anywhere to put the data. I don't want to buffer it up in RAM, since that could end up using a lot of RAM; and I don't want to just drop the data either, as client B might need it. So I go for the third option, which is to not select()-for-read-ready on client A's socket until client B has also connected. That way client A just blocks until everything is ready to go.

这或多或少也有效,但是在客户端 A 的套接字上不选择读取就绪的副作用是,如果客户端 A 决定关闭与服务器的 TCP 连接,则服务器不会收到通知这个事实——至少,直到客户端 B 出现并且服务器最终在客户端 A 的套接字上选择读取就绪,读取任何挂起的数据,然后获取套接字关闭通知(即 recv() 返回 0).

That more or less works too, but the side effect of not selecting-for-read-ready on client A's socket is that if client A decides to close his TCP connection to the server, the server doesn't get notified about that fact -- at least, not until client B comes along and the server finally selects-for-read-ready on client A's socket, reads any pending data, and then gets the socket-closed notification (i.e. recv() returning 0).

如果服务器有某种方式(及时地)知道客户端 A 何时关闭了他的 TCP 连接,我会更喜欢它.有没有办法知道这一点?在这种情况下轮询是可以接受的(例如,如果存在这样的函数,我可以让 select() 每分钟唤醒一次并在所有套接字上调用 IsSocketStillConnected(sock)).

I'd prefer it if the server had some way of knowing (in a timely manner) when client A closed his TCP connection. Is there a way to know this? Polling would be acceptable in this case (e.g. I could have select() wake up once a minute and call IsSocketStillConnected(sock) on all sockets, if such a function existed).

推荐答案

看来我的问题的答案是不,除非您愿意并能够修改 TCP 堆栈以访问必要的私有套接字状态信息".

It appears the answer to my question is "no, not unless you are willing and able to modify your TCP stack to get access to the necessary private socket-state information".

由于我无法做到这一点,我的解决方案是重新设计代理服务器以始终从所有客户端读取数据,并丢弃来自合作伙伴尚未连接的客户端的任何数据.这是非最优的,因为这意味着通过代理的 TCP 流不再具有使用 TCP 的程序所期望的类似流的可靠有序交付特性,但它足以满足我的目的.

Since I'm not able to do that, my solution was to redesign the proxy server to always read data from all clients, and throw away any data that arrives from a client whose partner hasn't connected yet. This is non-optimal, since it means that the TCP streams going through the proxy no longer have the stream-like property of reliable in-order delivery that TCP-using programs expect, but it will suffice for my purpose.

这篇关于有没有办法检测 TCP 套接字已被远程对等方关闭,而无需从中读取?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆