7

您如何设计一个在单个套接字上运行的读写循环(支持并行读写操作)?我必须使用多个线程吗?我的(java)解决方案有什么好处吗?那 sleep 命令呢?你如何在这样的循环中使用它?

我正在尝试使用 2 个线程:

public void run() {
    InputStream           clientInput;
    ByteArrayOutputStream byteBuffer;
    BufferedInputStream   bufferedInputStream;
    byte[]                data;
    String                dataString;
    int                   lastByte;

    try {
        clientInput         = clientSocket.getInputStream();
        byteBuffer          = new ByteArrayOutputStream();
        bufferedInputStream = new BufferedInputStream(clientInput);

        while(isRunning) {  

            while ((lastByte = bufferedInputStream.read()) > 0) {
                byteBuffer.write(lastByte);
            }
                data       = byteBuffer.toByteArray();  
                dataString = new String(data);
                byteBuffer.reset();     
        }   

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

public void run() {
    OutputStream clientOutput;
    byte[]       data;
    String       dataString;

    try {
        clientOutput = clientSocket.getOutputStream();

        while(isOpen) { 

            if(!commandQueue.isEmpty()) {
                dataString = commandQueue.poll();
                data       = dataString.getBytes();
                clientOutput.write(data);
            }                   
            Thread.sleep(1000);
        }       
        clientOutput.close();           
    } 
    catch (IOException e) {
        e.printStackTrace();
    } 
    catch (InterruptedException e) {
        e.printStackTrace();
    }
}

读取无法提供正确的结果,因为没有发送 -1。我该如何解决这个问题?

这个睡眠/写循环是一个好的解决方案吗?

4

2 回答 2

4

网络 I/O 基本上有三种方式:

  1. 阻塞。在这种模式下,读取和写入将阻塞,直到它们可以完成,所以如果你想同时做这两个,你需要为每个单独的线程。

  2. 非阻塞。在这种模式下,读写将返回零(Java)或在某些语言(C)中,当它们无法完成时,会返回状态指示(返回 == -1,errno=EAGAIN/EWOULDBLOCK),因此您不需要单独的线程,但是您确实需要第三个 API 来告诉您何时可以完成操作。这就是select()API 的目的。

  3. 异步 I/O,您可以在其中安排传输并返回某种句柄,您可以通过该句柄查询传输状态,或者在更高级的 API 中,回调。

当然不应该使用你在这里使用的while (in.available() > 0)/样式。很少有正确的用途,这不是其中之一,睡眠实际上是在浪费时间。数据可以在睡眠时间内到达,正常人会立即醒来。sleep()InputStream.available()read()

于 2012-04-25T09:54:26.957 回答
0

您应该在需要时使用布尔变量而不是 while(true) 来正确关闭线程。同样是的,您应该创建多个线程,每个连接的客户端一个,因为线程将自己阻塞,直到收到新数据(例如 DataInputStream().read() )。不,这不是一个真正的设计问题,每个库/框架或语言都有自己的方式从套接字监听,例如从 Qt 中的套接字监听你应该使用所谓的“信号和插槽”,而不是无限循环。

于 2012-04-25T09:21:32.737 回答