【问题标题】:Java Socket HTTP Server gets slow when multiple clients are connected连接多个客户端时,Java Socket HTTP 服务器变慢
【发布时间】:2017-03-14 11:00:02
【问题描述】:

我在Android中做一个M-JPEG Server,已经成功实现了,但是遇到一个问题:

我第一次连接到它(使用浏览器连接)时,流很好,我得到了实时预览,但是打开了一个新客户端(比如,重新加载页面或在新标签中打开),流变得越来越慢。即使我关闭了以前的客户端,它也不会提高性能。

我尝试过其他 M-JPEG Android Streamer(如 myMobKit),它并没有变慢。

这是我的服务器代码 -

public class StreamServer implements Runnable {
    public static Stack<byte[]> bufferStack;
        ...
    public StreamServer(int port) {
        ...
        bufferStack = new Stack<>();
        bufferStack.setSize(100);
    }
    public void start() {
        new Thread(this).start();
    }
    ...
    @Override
    public void run() {
        try {
            serverSocket = new ServerSocket(port);
            while (isRunning) {
                Socket socket = serverSocket.accept();
                new Thread(new StreamSocket(socket)).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public void addBufferToStack(byte[] buffer) {
        bufferStack.push(buffer);
    }
}

...还有 Socket 实现 -

public class StreamSocket implements Runnable {

private Stack<byte[]> bufferStack = StreamServer.bufferStack;
    ...
    StreamSocket(Socket socket) throws SocketException {
        this.socket = socket;
        this.socket.setTcpNoDelay(true);
        this.socket.setKeepAlive(false);
    ...
}
@Override
public void run() {
    if (!isStreaming) return;
    PrintStream output = null;
    try {
        output = new PrintStream(socket.getOutputStream());
        // Sent the initial header for M-JPEG.
    ...
        // Start the loop for sending M-JPEGs
        while (isStreaming && !socket.isClosed() && socket.isConnected()) {
            try {
                if (bufferStack.empty()) continue;
                byte[] buffer = bufferStack.pop();
                if (buffer == null) continue;
                ... (Some headers needed for M-JPEG streaming. Read it on Wikipedia)
                output.write(buffer);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        output.flush();
        output.close();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (output != null) output.close();
            if (!socket.isClosed() || socket.isConnected()) socket.close();
            isStreaming = false;
            socket = null;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
}

addBufferToStack(...) 在生成新的 JPEG 时调用(拍摄相机的预览帧,并通过本机代码处理成 JPG)。

我认为即使客户端断开连接后套接字线程也没有关闭,尽管我不确定。请帮忙,谢谢!

如果需要任何其他信息/代码,请告诉我,我会编辑问题并添加它。

编辑 -

bufferStack 在服务器启动时为空。服务器在 摄像头 + 其他一些东西启动之后启动。

【问题讨论】:

  • new Thread(new StreamSocket(socket));你有没有考虑开始这个话题?
  • 对不起,这里的代码不完整,忘记在这里添加start()。修复它。
  • 所以这不是真正的代码?真正的代码看起来像什么?
  • 请注意,即使另一端拔掉插头,isConnected 也会保持真实。
  • isConnected: "注意:关闭一个套接字并不会清除它的连接状态,这意味着这个方法对于一个关闭的套接字将返回true(见isClosed())如果它在关闭之前成功连接。”

标签: java android sockets serversocket mjpeg


【解决方案1】:

即使另一端结束连接,您的循环也会继续循环: (注意我的cmets)

while (isStreaming && !socket.isClosed() && socket.isConnected()) {
            try {
                if (bufferStack.empty()) continue;
                byte[] buffer = bufferStack.pop();
                if (buffer == null) continue;
                ... (Some headers needed for M-JPEG streaming. Read it on Wikipedia)
                output.write(buffer); // <-- will throw Exception if connection is broken
            } catch (Exception e) {
                e.printStackTrace();  // here you should also reset isStreaming
            }
        }

通过捕获异常(而不是实际处理它),您消除了连接已断开的信息。

检查isConnected 作为循环条件是超级流畅的 - 如果套接字一旦连接,它将始终为真。见https://docs.oracle.com/javase/8/docs/api/java/net/Socket.html#isConnected--

注意:关闭套接字并不会清除其连接状态,这意味着如果在关闭之前已成功连接,则此方法将为已关闭的套接字返回 true(参见 isClosed())。

我目前不能 100% 确定 isClosed 的行为,但我坚信只有当您调用 close 时它才会变为 true,而不是在底层流引发 IOException 时。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-02-13
    • 1970-01-01
    • 1970-01-01
    • 2016-07-14
    • 2018-06-24
    • 1970-01-01
    • 2011-09-22
    • 1970-01-01
    相关资源
    最近更新 更多