【问题标题】:Java erlang socket communicationJava erlang 套接字通信
【发布时间】:2016-09-25 03:16:48
【问题描述】:

我在通过线程读取和写入套接字时遇到问题。服务器使用 erlang,客户端使用 Java。我的做法是这样的:

PrintWriter printer = new PrintWriter(socket.getOutputStream(), true);
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
TransmitterTwo trans = new TransmitterTwo(socket);
trans.start(); // Gets the message from socket

TransmitterTwo 类:

public class TransmitterTwo extends Thread {
Socket socket;
String message;

TransmitterTwo(Socket socket) {
  this.socket = socket;
}

public String getMessageFromSocket() {
  return message;
}

public void run() {
  try {
    String response = null;
    BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
  while ((response = reader.readLine()) != null) {
    System.out.println("Server response: "+ response);
    this.message = response;
  }

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

问题出在主客户端类中。这个想法是:从控制台接收输入,将其发送到套接字,服务器处理逻辑并通过套接字发送响应。然后在这个客户端上,我检查响应并做我需要做的任何事情。这是一个注册流程,我注册,我收到“register_ok”,然后我登录……等等。我遇到问题的循环部分是这样的:

while(true) {
  String readerInput = reader.readLine(); // Read from console
  printer.println(readerInput.trim()); // Sends it to the socket

  while(trans.message == null);
  socketMessage = trans.message;

这是正确的方法吗?问题是'socketmessage'打印了之前收到的消息,就像..落后了一步,显然这是与线程相关的,但我无法弄清楚问题......帮助?谢谢

【问题讨论】:

    标签: java multithreading sockets erlang


    【解决方案1】:

    您当前的方法不是最理想的,因为您正在浪费主线程旋转等待该变量进行更新。由于内存可见性在 java 中的工作方式,它可能看起来永远不会被更新(即使它实际上是),或者当您访问该变量时您可能会得到陈旧的值。更健壮的方法是使用 java 中的一些内置集合在线程之间传递消息:

    public static void main(String[] args) {
        // This queue will be the link between the threads where 
        // they can pass messages to each other
        BlockingQueue<String> messages = new LinkedBlockingQueue<>();
    
        PrintWriter printer = new PrintWriter(socket.getOutputStream(), true);
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        TransmitterTwo trans = new TransmitterTwo(socket, queue);
        trans.start(); // Gets the message from socket
    
        ...
    
        while(true) {
              String readerInput = reader.readLine(); // Read from console
              printer.println(readerInput.trim()); // Sends it to the socket
    
              // Wait for the other thread to push a message in to the queue.
              String recv = messages.take();
        }
    }
    
    public class TransmitterTwo extends Thread {
        final Socket socket;
        final BlockingQueue<String> queue;
    
        TransmitterTwo(Socket socket, BlockingQueue<String> queue) {
            this.socket = socket;
            this.queue = queue;
        }
    
        public void run() {
            try {
                String response = null;
                BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                while ((response = reader.readLine()) != null) {
                    System.out.println("Server response: " + response);
                    // Add the response from the server to the queue
                    queue.add(response);
                }
    
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    

    这种方法永远不会得到陈旧的值,并且主线程上的 take() 操作将阻塞,直到服务器有一些响应。

    【讨论】:

    • 哇,这比我预期的要好:)。我很绝望,因为我的职业未来取决于这个哈哈。那么,您是否认为通过您的方法,我将能够拥有 N 个客户端并正确获取消息?因为我不想在线程之间传递值,所以我希望每个客户端都与套接字通信并拥有一个独立的发送器/接收器。它就像一个服务,每个客户端都可以通过套接字进行对话和收听......不过,我会尝试这种方法并在之后回答。非常感谢,我真的很感激。
    • 只是一个小错误。发送到套接字的字符串最后总是有一个“\n”,即使使用 trim() 方法,它也会发送一个 \n ...你知道为什么吗?
    • 已修复。必须使用printer.prin 然后刷新,再次感谢。来自葡萄牙的欢呼
    猜你喜欢
    • 2021-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多