【问题标题】:serverSocket.accept() slow or non-respondingserverSocket.accept() 缓慢或无响应
【发布时间】:2016-06-30 12:59:17
【问题描述】:

我们在java(windows/server上的eclipse)和android app(android studio/client)之间创建了一个服务器客户端关系。通信似乎很好,但有时连接速度非常慢,直到应用程序和服务器不再响应。然而,没有给出真正的错误,也没有什么模式可以判断连接何时正常或何时连接缓慢。

我们在堆栈中寻找答案,但我们只能找到有关输出和输入流的答案。但是,一旦建立连接(serverSocket.accept()),程序就会运行良好,并且流的创建速度非常快。因此,我们认为问题在于服务器端创建套接字。该程序最多只能处理 30 个客户端,并且唯一的通信存在字符串(因此不会传输大量数据)。

注意:当一个连接接受速度很慢时,来自客户端的下一个即将到来的请求必须等待。当轮到他们时,他们会再次随机快速或缓慢地被服务器接受。所有连接都在端口 8080 上进行。

我们的服务器和客户端的代码如下,有人知道为什么连接(在某些随机时间)这么慢吗?

服务器:

    public void run() {
        keepGoing = true;
    try {
        serverSocket = new ServerSocket(port);

        while (keepGoing) {
            display("Server waiting for Clients on port " + port + ".");

            Socket socket = serverSocket.accept(); //<---our problem
            if (!keepGoing)     break;
            ClientThread t = new ClientThread(socket, this); //<---program doesnt reach this code when it is slow. One client thread exists for each connection.
    }catch (IOException e) {
        String msg = sdf.format(new Date())
                + " Exception on new ServerSocket: " + e + "\n";
        display(msg);
        }
    }

客户端线程代码:(如果慢则无法到达)

    public ClientThread(Socket socket, Server s) {
        this.server = s;
        this.socket = socket;        
    System.out.println("Thread trying to create Object Input/Output Streams");
    try {
        // make streams
        sOutput = new ObjectOutputStream(socket.getOutputStream());
        sInput = new ObjectInputStream(socket.getInputStream());

        // read user account info
        String input = (String) sInput.readObject();
        String[] accountInfo = input.split(";");
        username = accountInfo[0];
        password = accountInfo[1];
    } "catch all problems"
    }

客户端(安卓)

    Thread connect = new Thread(new Runnable() {
    @Override
        public void run()
        {
            try
            {
                socket = new Socket(ip.getText().toString(), portNr);
                sOutput = new ObjectOutputStream(socket.getOutputStream());
                sInput = new ObjectInputStream(socket.getInputStream());
            }

            catch (UnknownHostException e ){
                e.printStackTrace();
            } catch(IOException e ){
                e.printStackTrace();
            }

            "sending account information"
        }
    });
    connect.start();
    try {
        connect.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

非常感谢!

【问题讨论】:

    标签: java android performance sockets serversocket


    【解决方案1】:

    在开始循环之前,您应该在run() 方法中创建ClientThread 中的流。不在构造函数中。否则,您将在接受线程中执行 I/O,这会减慢它的速度。

    我不知道你为什么要在客户端创建一个线程只是为了立即加入它。

    【讨论】:

    • 我尝试重新定位流代码的创建,问题似乎变得更糟。关于加入的位置:我按照教程(第一次服务器客户端编程)并复制了代码片段。我也不知道它为什么在那里,我应该删除它吗?
    • 您应该删除 线程。这不仅仅是关于“连接的位置”。劣质代码,无论其来源如何。
    • 请发布您当前的代码。将其编辑到您的问题中。
    • 如果我删除线程,应用程序在尝试建立连接时会崩溃。 “应用程序停止运行”。删除 join() 时,出现错误:尝试在空对象引用上调用虚拟方法 'java.lang.Object java.io.ObjectInputStream.readObject()'
    • 安妮,我无法评论我看不到的代码。请按照我 8 小时前的要求做,现在请在“已删除线程”中包含客户端代码。
    【解决方案2】:

    您应该将您的主服务器循环 (while(keepGoing)...) 提取到一个 run 方法中,并使服务器实现 Runnabel 接口。然后创建一个新线程并启动它。

    例子:

    public class Server implements Runnable{
        private Thread thread;
        public Server(){
            thread = new Thread(this);
            thread.start(); //I would create start() and stop() methods but for simplicity I just use thread.start()
        }
    
        @Override
        public void run(){
            //while....
        }
    }
    

    我希望你明白我想说的话,否则只需发表评论,我将升级我的示例;)

    【讨论】:

    • 已经是这样了,我忘了把它包含在代码标题中,借口:) 生病更新标题。
    【解决方案3】:

    原来我们遇到了路由器问题。将所有平板电脑和计算机连接到本地热点时,它运行超级流畅!坦克每个人的帮助:D

    【讨论】:

    • 别忘了把你的答案标记为正确的:-)。
    【解决方案4】:

    编辑:试试这里提到的 BufferedStreamReader:Java socket performance bottleneck: where?

    代替:

    sOutput = new ObjectOutputStream(socket.getOutputStream());
    

    用途:

    sOutput = new ObjectOutputStream(new BufferedOutputStream(socket.getOutputStream()));
    

    并用以下方法冲洗它:

    sOutput.flush();
    

    同样适用于 InputStream,使用 BufferedInputStream。

    【讨论】:

    • 这段代码是在serverSocket.accept()之前还是之后添加的; ?
    • 接受后,我在上面的答案中添加了代码
    • 没有帮助 :( 仍然没有来自 clientthread 的构造函数的 autput :(
    • 奇怪的事情...我们根据您的建议更改了我们的代码,没有工作,改回来,现在它似乎运行正常...我不知道了哈哈!
    • 我搜索了一下,发现您应该使用 BufferedOutputStream。看看这个链接,希望对你有帮助:stackoverflow.com/questions/4451410/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-24
    • 2021-08-17
    • 2023-03-12
    • 1970-01-01
    相关资源
    最近更新 更多