通过java中的套接字进行全双工通信

时间:2015-08-12 13:34:25

标签: java multithreading sockets

我可以使用两个不同的线程来读取和写入同一个套接字,而不需要在java中进行任何同步吗?

我的代码是 -

public class Server {

    public static void main(String[] args) {
        Serve s = new Serve();
    }
}
class Serve {

ServerSocket sS;
String serverAddress;
int port;

public Serve() {
    serverAddress = "127.0.0.1";
    port = 8091;
    try  {
        sS = new ServerSocket(port);
        System.out.println("Server listening on port " + port+ " ...");
        Socket incomming = sS.accept();
        System.out.println("Connected to Client.");
        Runnable r = new Read(incomming);
        Runnable w = new Write(incomming);
        Thread read = new Thread(r);
        Thread write = new Thread(w);
        read.start();
        write.start();
        incomming.close();
        sS.close();
    }
    catch(IOException e) {
        e.printStackTrace();    
    }
}
}
class Read implements Runnable {

Socket readSocket;

public Read(Socket readSocket) {
    this.readSocket = readSocket;
}

@Override
public void run() {
    try {
        InputStream inStream = readSocket.getInputStream();
        try (Scanner in = new Scanner(inStream)) {
            boolean done = false;
            PrintWriter out = new PrintWriter(System.out, true);
            while(!done && in.hasNextLine()) {
                String line = in.nextLine();
                out.println("Client>" + line);
                if(line.trim().equals("BYE")) done = true;
            }
        }
    }
    catch(Exception e) {
        e.printStackTrace();
    }


}

}

class Write implements Runnable {

Socket writeSocket;

public Write(Socket writeSocket) {
    this.writeSocket = writeSocket;
    System.out.println("This is printed on the client terminal");
}

@Override
public void run() {
    try {
        OutputStream outStream = writeSocket.getOutputStream();
        try (Scanner in = new Scanner(System.in)) {
            boolean done = false;
            PrintWriter out = new PrintWriter(outStream, true);
            while(!done && in.hasNextLine()) {
                System.out.print("Server>");
                String line = in.nextLine();
                out.println(line);
                if(line.trim().equals("BYE")) done = true;
            }
         }
    }
    catch(Exception e) {
        System.out.println("Exception thrown here");
        e.printStackTrace();
    }


}

}

两个问题 -

  1. Write构造函数中的字符串将打印在客户端终端上。为什么会这样?

  2. 为什么在Write run()方法中抛出异常?

1 个答案:

答案 0 :(得分:2)

  

我可以使用两个不同的线程来读取和写入同一个套接字,而不需要在java中进行任何同步吗?

您无法避免同步,因为Socket的实现已经同步。

如果只有一个线程读取和另一个线程写入,则可以避免其他同步。

  

Write构造函数中的字符串将打印在客户端终端上。为什么会这样?

最有可能的原因是您也在客户端上运行该代码。

  

为什么在Write run()方法中抛出异常?

您有错误,如果您阅读它并告诉我们它是什么(包括堆栈跟踪)会更容易诊断

注意:线程需要一些时间来启动和运行。如果立即关闭连接,线程可能甚至没有机会在关闭连接之前读取连接。

    read.start();
    write.start();
    incomming.close(); // == kill the connection

而不是使用

 while(!done ...) {

    if (condition)
        done = true;
 }

您可以使用

 while(...) {

    if (condition)
       break;
 }