读/写java服务器套接字的最佳实践

时间:2012-04-25 08:17:11

标签: java sockets networking

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

我正在尝试使用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。 我该如何解决这个问题?

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

2 个答案:

答案 0 :(得分:4)

基本上有三种方法可以进行网络I / O:

  1. 阻止。在这种模式下,读取和写入将被阻塞,直到它们可以实现,因此如果您想同时执行这两个操作,则需要为每个执行两个线程。

  2. 无阻塞。在这种模式下,读取和写入将返回零(Java)或在某些语言(C)中无法满足时返回状态指示(return == -1,errno = EAGAIN / EWOULDBLOCK),因此您不需要单独的线程,但是你确实需要第三个API来告诉你什么时候可以实现 的操作。这是select() API。

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

  5. 当然永远不会使用您在此处使用的while (in.available() > 0) / sleep()样式。 InputStream.available()几乎没有正确的用法,这不是其中之一,睡眠实际上是浪费时间。数据可以在睡眠时间内到达,正常read()会立即唤醒。

答案 1 :(得分:0)

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