【问题标题】:Multiple non-simultaneous Java client-server connections using always the same port始终使用相同端口的多个非同时 Java 客户端-服务器连接
【发布时间】:2011-12-09 03:07:48
【问题描述】:

我正在尝试测试一个场景,其中一台服务器接受来自一个客户端的连接(每次一个),始终使用相同的端口(在服务器端和客户端)。

目的是让 1 个客户端应用程序以大于 100/min 的速率发送少量数据。显而易见的解决方案是在客户端和服务器之间建立一个始终连接的链接,但这是生产的东西,需要对已经实现的代码进行更大的更改。使用我们今天实施的解决方案,TIME_WAIT 中的连接数始终为 +-1K,我想摆脱它们。

我已经实现了一个简单的测试器,代码是:

public class Server {
    public static void main(String[] args) {
        ServerSocket ssock = null;
        try {
            ssock = new ServerSocket();
            ssock.bind(new InetSocketAddress(Common.SERVER_PORT));
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(-1);
        }

        while(true){
            try{
                Socket cSock = ssock.accept();

                BufferedReader reader = new BufferedReader(new InputStreamReader(cSock.getInputStream()));
                reader.readLine();

                PrintWriter writer = new PrintWriter(cSock.getOutputStream());
                writer.println(Common.SERVER_SEND);
                writer.flush();

                reader.close();
                writer.close();
                cSock.close();

            }catch (Exception e) {
                System.out.println(e.getClass().getName() + ": " + e.getMessage());
            }
        }
    }
}


public class Client {

    public static void main(String[] args) throws Exception {
        InetSocketAddress cliAddr = new InetSocketAddress(
                InetAddress.getByName(args[0]), 
                Common.CLIENT_PORT);

        InetSocketAddress srvAddr = new InetSocketAddress(
                InetAddress.getByName(args[1]), 
                Common.SERVER_PORT);

        for(int j=1;j<=50;j++){
            Socket sock = null;
            try{
                sock = new Socket();
                sock.setReuseAddress(true);
                sock.bind(cliAddr);
                sock.connect(srvAddr);

                PrintWriter writer = 
                        new PrintWriter(
                                sock.getOutputStream());

                writer.println(Common.CLIENT_SEND);
                writer.flush();

                BufferedReader reader = 
                        new BufferedReader(
                                new InputStreamReader(
                                        sock.getInputStream()));
                reader.readLine();

            }catch (Exception e) {
                System.out.println(e.getClass().getName() + ": " + e.getMessage());
                System.exit(-1);
            }finally{
                if(sock!=null) sock.close();
                System.out.println("Done " + j);
            }
        }
    }
}

public class Common {
    public static final int SERVER_PORT = 9009;
    public static final int CLIENT_PORT = 9010;
    public static final String CLIENT_SEND = "Message";
    public static final String SERVER_SEND = "OK";
}

在 windows 主机上执行客户端和服务器时,在一个客户端执行中我总是得到

java.net.ConnectException: Connection timed out

在 linux 主机中执行客户端和服务器时,在某些客户端执行中我得到一个

java.net.NoRouteToHostException: Cannot assign requested address

我一直对这种行为感到头疼。有人可以告诉我是否可以做我想做的事,以及我做错了什么?

【问题讨论】:

  • 所以你有很多连接,你想用一大块代码加速它,但它不起作用,帮我弄清楚?或者您的问题是关于您的客户端代码似乎无法找到服务器的事实?如果是后者,您应该编辑您的问题,使其显而易见。
  • 我只想改进已经实现的大块代码......上面的代码只是一个测试应用程序!
  • 客户端确实找到、连接并与服务器交换了一些消息,但它不像时钟那样工作。我猜这是因为这两个应用程序无法控制两端连接的关闭,一切都搞混了。
  • 为什么总是使用同一个客户端端口?这是不好的做法。
  • 我不相信:java.net.NoRouteToHostException: Cannot assign requested address。我相信这是BindException

标签: java sockets reusability connection


【解决方案1】:

如果您想摆脱 TIME_WAIT 状态,请不要成为接收关闭的对等方。成为发起收盘的对等方。在这种情况下,在读取响应后立即关闭连接,并让服务器循环寻找另一个请求,以便它读取 EOF,而不是在发送响应后立即关闭连接。然而,这只会使问题变得更糟,因为所有 TIME_WAIT 状态都会在服务器而不是客户端累积。另一方面,服务器现在的结构是每个连接接受多个请求,因此您所要做的就是让客户端使用连接池,所有问题都得到解决。

【讨论】:

  • 将 TIME_WAIT 连接传递到服务器端不是一种选择。在我看来,我将不得不在客户端和服务器中做出更大的改变......
  • 我同意这不是一个选择,确实我说过,但是我所说的其余部分呢?为什么要使用单个客户端端口?你打算什么时候回答这里被问到的问题?
猜你喜欢
  • 2021-10-10
  • 1970-01-01
  • 2013-05-27
  • 2021-10-03
  • 2019-07-12
  • 2014-08-18
  • 2016-10-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多