使用同一主机创建套接字
在Java中,当创建具有相同参数的套接字时(忽略此代码将抛出ConnectException
的事实):
Socket s1 = new Socket("127.0.0.1", 7575);
Socket s2 = new Socket("127.0.0.1", 7575);
s1
等于s2
吗? 我的意思是,关闭 s1 会对 s2 产生相同的效果吗?
如果没有,我怎样才能关闭一个我没有引用的套接字(只有创建它的IP和端口)。
谢谢。
In Java, when creating sockets with the same parameters (ignoring the fact that this code will throw a ConnectException
):
Socket s1 = new Socket("127.0.0.1", 7575);
Socket s2 = new Socket("127.0.0.1", 7575);
Is s1
equal to s2
?
I mean, will closing s1
have the same effect on s2
?
If not, how can I close a socket I don't have a reference to (only having the ip and port it was created with).
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
s1
和s2
引用两个不同的Socket
实例,因此关闭一个实例不会对另一个实例产生直接影响。不过,您不会仅仅因为两个套接字连接到相同的地址和端口而得到 ConnectException。只要目标服务器能够接受它们,就没有什么可以阻止您将两个套接字连接到相同的目标地址和端口。当您仅指定目标地址/端口对时,操作系统会自动从 临时端口范围(编号高于 1024)。重要的是(远程地址、远程端口、本地地址、本地端口)组合(称为 4 元组)是唯一的;这就是底层 TCP/IP 堆栈在需要将传入数据包与其相应套接字相匹配时区分套接字的方式,也是服务器如何能够在同一端口上接受多个连接的方式。
如果您这样做:
那么您将在第二个套接字的绑定尝试中收到 BindException ,因为只允许服务器套接字创建绑定到同一源端口的套接字。这是因为在
accept()
期间,4 元组是完全已知的并且可以确定其唯一性。 这个问题有更多细节。这是一个简单的测试类,用于演示当多个套接字连接到同一目标主机和端口时会发生什么:
}
输出将类似于:
首先您可以看到,要使套接字唯一,只需 4 元组中的一个部分不同即可。即使我们从 127.0.0.1 连接到 127.0.0.1 端口 55555,源端口是唯一的这一事实就足够了。
当 JVM 需要要求操作系统执行操作时,套接字由它们的引用变量来标识,这些引用变量对应于套接字描述符,它们不可能被混淆。
我认为,当您不拥有对套接字的引用时,强制关闭套接字是不可能的。我能想到的唯一方法是调用底层操作系统的本机库(通过 JNI)或系统实用程序(使用 Runtime.getRuntime().exec(command) 或相似的)。您需要通过其 4 元组来识别连接,然后请求将其关闭,但您需要具有提升的权限才能执行此操作。
s1
ands2
refer to two distinctSocket
instances so closing one will have no direct effect on the other.You would not get a
ConnectException
just because of two sockets connecting to the same address and port though. There is nothing stopping you connecting two sockets to the same target address and port as long as the target server is able to accept them. When you only specify the target address/port pair the operating system automatically assigns a local port for the socket from the ephemeral port range (numbering somewhere above 1024). What matters is that the(remote address, remote port, local address, local port)
combination (known as a 4-tuple) is unique; this is how the socket is differentiated by the underlying TCP/IP stack when it needs to match incoming packets to their corresponding sockets and is how a server is able to accept multiple connections on the same port.If you were to do:
then you would get a
BindException
on the second socket's bind attempt, since only server sockets are allowed to create sockets bound to the same source port. This is because duringaccept()
the 4-tuple is fully known and its uniqueness can be determined. This SO question has more detail.Here is a simple test class to demonstrate what happens when multiple sockets connect to the same target host and port:
}
And the output will be something like:
You can see firstly that all that is needed for the sockets to be unique is a single part of the 4-tuple to be different. Even though we are connecting from 127.0.0.1 to 127.0.0.1 port 55555, the fact that the source port is unique is enough.
The sockets are identified by their reference variables which correspond to socket descriptors when the JVM needs to ask the OS to perform operations, there is no way that they can be confused.
Forcing a socket to be closed when you don't own a reference to it is impossible I think. The only way to do it that I can think of would be to call out to the underlying operating system's native libraries (via JNI) or system utilities (using
Runtime.getRuntime().exec(command)
or similar). You would need to identify the connection by its 4-tuple and then request it be closed, but you would need to have elevated privileges to do so.答案是否定的。这不会像您预期的那样表现。在任何给定时间只能建立一个到端口的连接(不包括行为略有不同的异步调用)。
如果您单步执行代码并进行检查,您应该会发现 s1 设置为连接状态,而 s2 则断开连接。
至于如何关闭您没有引用的套接字,它不会那样工作。您必须创建 Socket 实例并在程序执行过程中维护它。如果引用丢失或被丢弃,我相信您必须重新创建 Socket 对象。
The answer is no. This won't behave like you are anticipating. Only one connection to a port can be established at any given time (excluding asynchronous calls which behave somewhat differently).
if you stepped through your code and checked, you should find that s1 is set to be connected while s2 is disconnected.
As for how to close a socket you don't have a reference to, it doesn't function that way. You must create the instance of the Socket and maintain it throughout the execution of your program. If the reference is lost or disposed of, I believe you must recreate the Socket object.