Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用同一主机创建套接字_Java_Sockets_Networking - Fatal编程技术网

Java 使用同一主机创建套接字

Java 使用同一主机创建套接字,java,sockets,networking,Java,Sockets,Networking,在Java中,当创建具有相同参数的套接字时(忽略此代码将引发ConnectException): s1是否等于s2? 我的意思是,关闭s1会对s2产生同样的影响吗 如果没有,我如何关闭一个没有引用的套接字(只有创建它时使用的ip和端口) 谢谢。答案是否定的。这不会像你预期的那样。在任何给定时间只能建立一个到端口的连接(不包括行为稍有不同的异步调用) 如果您仔细检查代码并进行检查,您应该会发现s1设置为已连接,而s2设置为已断开连接 至于如何关闭一个没有引用的套接字,它不会以这种方式工作。您必须创

在Java中,当创建具有相同参数的套接字时(忽略此代码将引发
ConnectException
):

s1
是否等于
s2
? 我的意思是,关闭
s1
会对
s2
产生同样的影响吗

如果没有,我如何关闭一个没有引用的套接字(只有创建它时使用的ip和端口)


谢谢。

答案是否定的。这不会像你预期的那样。在任何给定时间只能建立一个到端口的连接(不包括行为稍有不同的异步调用)

如果您仔细检查代码并进行检查,您应该会发现s1设置为已连接,而s2设置为已断开连接


至于如何关闭一个没有引用的套接字,它不会以这种方式工作。您必须创建套接字实例,并在整个程序执行过程中维护它。如果引用丢失或已处理,我相信您必须重新创建套接字对象。

s1
s2
引用两个不同的
套接字
实例,因此关闭其中一个不会对另一个产生直接影响

但是,仅仅因为两个套接字连接到同一地址和端口,您不会得到
连接异常。只要目标服务器能够接受,就不会阻止您将两个套接字连接到相同的目标地址和端口。当您仅指定目标地址/端口对时,操作系统会自动从为套接字分配一个本地端口(编号在1024以上)。重要的是
(远程地址、远程端口、本地地址、本地端口)
组合(称为4元组)是唯一的;这就是当套接字需要将传入的数据包与其对应的套接字进行匹配时,底层TCP/IP堆栈如何区分套接字,以及服务器如何能够在同一端口上接受多个连接

如果你要做:

    Socket s1 = new Socket();
    s1.bind(new InetSocketAddress("127.0.0.1", 7070));
    s1.connect(new InetSocketAddress("127.0.0.1", SERVER_PORT));

    Socket s2 = new Socket();
    s2.bind(new InetSocketAddress("127.0.0.1", 7070));
    s2.connect(new InetSocketAddress("127.0.0.1", SERVER_PORT));
然后,您将在第二个套接字的绑定尝试中得到一个
BindException
,因为只有服务器套接字才允许创建绑定到同一源端口的套接字。这是因为在
accept()
期间,4元组是完全已知的,并且可以确定其唯一性。有更多的细节

下面是一个简单的测试类,演示当多个套接字连接到同一目标主机和端口时会发生什么:

public class ConnectTest {

static ServerSocket serverSock;
static List<Socket> acceptedSockets = Collections.synchronizedList(new ArrayList<Socket>());
static final int SERVER_PORT = 55555;

static class Server implements Runnable {
    @Override
    public void run() {
        try {
            serverSock = new ServerSocket();
            serverSock.bind(new  InetSocketAddress("127.0.0.1", 55555));
            while (true)
                { acceptedSockets.add(serverSock.accept()); }
        } catch (IOException e) { e.printStackTrace(); }
    }
}

public static void main(String[] args) throws Exception {
    new Thread(new Server()).start();

    List<Socket> clientSockets = new ArrayList<Socket>();
    // open 10 sockets to the same target address/port
    for (int i = 0; i < 10; i++) {
        Socket s = new Socket("127.0.0.1", 55555);
        System.out.println("Local address: " + s.getLocalSocketAddress() +
                "    Remote address: " + s.getRemoteSocketAddress());
        clientSockets.add(s);
    }

    // now close half
    for (Socket s : clientSockets.subList(0, 5))
            s.close();

    // now list them again
    System.out.println("\n\n Socket list after some closed:");
    for (Socket s : clientSockets) {
        if (s.isClosed()) {
            System.out.println("* Socket Closed *");
        } else {
            System.out.println("Local address: " + s.getLocalSocketAddress() +
                "    Remote address: " + s.getRemoteSocketAddress());
        }
    }
}
首先,您可以看到,要使套接字唯一,所需的只是使4元组的一个部分不同。尽管我们从127.0.0.1连接到127.0.0.1端口55555,但源端口是唯一的这一事实就足够了

套接字由它们的引用变量标识,这些引用变量对应于套接字描述符。当JVM需要请求操作系统执行操作时,它们不会被混淆


我认为,当您没有对套接字的引用时,强制关闭套接字是不可能的。我能想到的唯一方法是调用底层操作系统的本机库(通过JNI)或系统实用程序(使用
Runtime.getRuntime().exec(command)
或类似工具)。您需要通过其4元组来识别连接,然后请求关闭连接,但您需要具有更高的权限才能这样做。

如果您可以这样做,(即通过
s2
关闭
s1
的套接字),那么
s1
的用户将非常恼火……感谢您的回答。“在任何给定时间,只能建立一个到端口的连接(不包括行为稍有不同的异步调用)。“这是不正确的,重要的是4元组是唯一的,请参见下文。”“异步调用”是一种转移注意力的手段,它们与此无关。@willcroz承认我对网络编程的理解是有限的。谢谢您的更正。@ibeita此答案不正确。s1和s2都将被连接,除非任一构造函数引发异常。
public class ConnectTest {

static ServerSocket serverSock;
static List<Socket> acceptedSockets = Collections.synchronizedList(new ArrayList<Socket>());
static final int SERVER_PORT = 55555;

static class Server implements Runnable {
    @Override
    public void run() {
        try {
            serverSock = new ServerSocket();
            serverSock.bind(new  InetSocketAddress("127.0.0.1", 55555));
            while (true)
                { acceptedSockets.add(serverSock.accept()); }
        } catch (IOException e) { e.printStackTrace(); }
    }
}

public static void main(String[] args) throws Exception {
    new Thread(new Server()).start();

    List<Socket> clientSockets = new ArrayList<Socket>();
    // open 10 sockets to the same target address/port
    for (int i = 0; i < 10; i++) {
        Socket s = new Socket("127.0.0.1", 55555);
        System.out.println("Local address: " + s.getLocalSocketAddress() +
                "    Remote address: " + s.getRemoteSocketAddress());
        clientSockets.add(s);
    }

    // now close half
    for (Socket s : clientSockets.subList(0, 5))
            s.close();

    // now list them again
    System.out.println("\n\n Socket list after some closed:");
    for (Socket s : clientSockets) {
        if (s.isClosed()) {
            System.out.println("* Socket Closed *");
        } else {
            System.out.println("Local address: " + s.getLocalSocketAddress() +
                "    Remote address: " + s.getRemoteSocketAddress());
        }
    }
}
Local address: /127.0.0.1:43088    Remote address: /127.0.0.1:55555
Local address: /127.0.0.1:43089    Remote address: /127.0.0.1:55555
Local address: /127.0.0.1:43090    Remote address: /127.0.0.1:55555
Local address: /127.0.0.1:43091    Remote address: /127.0.0.1:55555
Local address: /127.0.0.1:43092    Remote address: /127.0.0.1:55555
Local address: /127.0.0.1:43093    Remote address: /127.0.0.1:55555
Local address: /127.0.0.1:43094    Remote address: /127.0.0.1:55555
Local address: /127.0.0.1:43095    Remote address: /127.0.0.1:55555
Local address: /127.0.0.1:43096    Remote address: /127.0.0.1:55555
Local address: /127.0.0.1:43097    Remote address: /127.0.0.1:55555


 Socket list after some closed:
* Socket Closed *
* Socket Closed *
* Socket Closed *
* Socket Closed *
* Socket Closed *
Local address: /127.0.0.1:43093    Remote address: /127.0.0.1:55555
Local address: /127.0.0.1:43094    Remote address: /127.0.0.1:55555
Local address: /127.0.0.1:43095    Remote address: /127.0.0.1:55555
Local address: /127.0.0.1:43096    Remote address: /127.0.0.1:55555
Local address: /127.0.0.1:43097    Remote address: /127.0.0.1:55555