简体   繁体   English

serverSocket.accept()缓慢或无响应

[英]serverSocket.accept() slow or non-responding

We created a server client relation between java (eclipse on windows/server) and android app (android studio/client). 我们在Java(Windows / Server上的日食)和android应用(android Studio / Client)之间创建了服务器客户端关系。 The communication seems fine, but sometimes the connecting is horrably slow, up to the point where the app and and server don't respond anymore. 通讯似乎正常,但有时连接速度非常慢,直到应用程序和服务器不再响应为止。 Yet, no real error is given and there is no pattern to when the connection goes well or when it is slow. 但是,没有给出真正的错误,也没有模式说明连接何时进行良好或缓慢。

We looked for answers here at stack, but we could only find answers regarding the output and input streams. 我们在堆栈中寻找答案,但是我们只能找到有关输出和输入流的答案。 However, once the connection (serverSocket.accept()) is made, the program runs fine and the streams are created super fast. 但是,一旦建立了连接(serverSocket.accept()),程序就可以正常运行,并且流的创建速度非常快。 Thus we think the problem lies with the server side creation of sockets. 因此,我们认为问题出在套接字的服务器端创建上。 The program only has to handle a maximum of 30 clients, and the only communication exists of strings (so no enormous data transfers). 该程序最多只能处理30个客户端,并且唯一的通信存在字符串(因此没有大量的数据传输)。

Note: when one connection acceptation is slow, the next upcomming requests from clients have to wait. 注意:当一个连接接受缓慢时,来自客户端的下一个即将到来的请求必须等待。 When it's their turn they are again randomely fast or slowly accepted by the server. 轮到他们时,服务器会再次随机或缓慢地接受它们。 All connections are made on port 8080. 所有连接均在端口8080上进行。

The code of our server and client are given below, does anybody know why the connection is (at some random times) so slow? 下面提供了我们服务器和客户端的代码,有人知道为什么连接(在某些随机时间)这么慢吗?

SERVER: 服务器:

    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);
        }
    }

CLIENT THREAD CODE: (not reached if slow) 客户线程代码:(如果速度较慢,则无法访问)

    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"
    }

CLIENT (android) 客户(android)

    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();
    }

Thanks so much! 非常感谢!

You should extract your main server loop (while(keepGoing)...) into a run method and make the server implement the Runnabel interface. 您应该将主服务器循环(while(keepGoing)...)提取到run方法中,并使服务器实现Runnabel接口。 Then create a new Thread and start it. 然后创建一个新线程并启动它。

Example: 例:

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....
    }
}

I hope you get what I want to say, otherwise just comment and I will upgrade my example ;) 我希望您能得到我想说的话,否则请发表评论,我将升级我的示例;)

You should make the streams in the ClientThread in the run() method, before you start looping. 在开始循环之前,应在run()方法的ClientThread中创建流。 Not in the constructor. 不在构造函数中。 Otherwise you are doing I/O in the accept thread, which slows it down. 否则,您将在接受线程中执行I / O,这会降低它的速度。

I have no idea why you're creating a thread in the client only to join it immediately. 我不知道为什么您要在客户端中创建一个线程只是为了立即加入它。

Turns out we had a router issue. 原来我们遇到了路由器问题。 When connecting all tablets and computer to a local hotspot it ran super smooth! 将所有平板电脑和计算机连接到本地热点时,它运行起来非常流畅! Tanks everyone for the help :D 坦克大家的帮助:D

EDIT: Try a BufferedStreamReader mentioned here: Java socket performance bottleneck: where? 编辑:尝试这里提到的BufferedStreamReader: Java套接字性能瓶颈:在哪里?

Instead of: 代替:

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

Use: 采用:

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

and flush it with: 并用以下方法冲洗:

sOutput.flush();

Same goes for the InputStream, use BufferedInputStream. InputStream也一样,使用BufferedInputStream。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM