当套接字接收数据时,Java Socket 中是否有事件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28137972/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 13:03:30  来源:igfitidea点击:

Is there an event in Java Socket when socket receive data?

javasockets

提问by Nicola Bena

I write a Swing Java program, with one client and one server with Socket of java.io. When client push a button something is send to the server and then the server should send something to the client. To implement this, I need to know if there is and event like "onClientRead" in C++, because I have some other different buttons that do other things, so I cannot put the ReadLine() method in every of those. I know that I can use the the socket in java.nio, but if there is something in the socket of java.io it is better. Thanks.

我写了一个 Swing Java 程序,一个客户端和一个服务器,带有 java.io 的 Socket。当客户端按下按钮时,一些东西被发送到服务器,然后服务器应该向客户端发送一些东西。为了实现这一点,我需要知道 C++ 中是否有像“onClientRead”这样的事件,因为我有一些其他不同的按钮可以做其他事情,所以我不能把 ReadLine() 方法放在每个按钮中。我知道我可以使用 java.nio 中的套接字,但是如果 java.io 的套接字中有一些东西就更好了。谢谢。

回答by InPursuit

The InputStream returned from your Socket on both ends will block if there is no data to be read (i.e. the read() method on the InputStream will not return until data is read). If you are doing the read() in the SwingEventThread (i.e. when the user clicks a button) then your UI will appear to lock up. The available() method on InputStream will return a number greater than 0 if there are bytes available to be read so you could use that.
However, it sounds like you should write some additional code that exists outside of your GUI which reads from the InputStream and fires its own event when data is read. Your GUI can then listen for that event. Something like this:

如果没有要读取的数据,则从两端的 Socket 返回的 InputStream 将阻塞(即 InputStream 上的 read() 方法在读取数据之前不会返回)。如果您在 SwingEventThread 中执行 read()(即当用户单击按钮时),那么您的 UI 将显示为锁定。如果有可用字节可供读取,则 InputStream 上的 available() 方法将返回一个大于 0 的数字,以便您可以使用它。
但是,听起来您应该编写一些存在于 GUI 之外的附加代码,这些代码从 InputStream 读取并在读取数据时触发自己的事件。然后,您的 GUI 可以侦听该事件。像这样的东西:

public class InputStreamReader
  implements Runnable
{
   protected InputStream in;
   protected List<ChangeListener> listeners;

   public InputStreamReader( InputStream in )
   {
     this.in = in;
     this.listeners = new ArrayList<ChangeListener>();
   }

   public void addChangeListener( ChangeListener l )
   {
     this.listeners.add( l );
   }

   public void run()
   {
     byte[] bytes = new byte[256]; //make this whatever you need
     in.read( bytes );

     //need some more checking here to make sure 256 bytes was read, etc.
     //Maybe write a subclass of ChangeEvent
     ChangeEvent evt = new ChangeEvent( bytes );
     for( ChangeListener l : listeners )
     {
       l.stateChanged( evt );
     }
   }
}

This class is a "Runnable" since the InputStream read method blocks so it needs to be run in a different thread. To start this class:

这个类是一个“Runnable”,因为 InputStream 读取方法阻塞,所以它需要在不同的线程中运行。开始这堂课:

InputStreamReader r = new InputStreamReader( in );
//add your listener here
Thread t = new Thread( r );
t.start();

回答by user3558040

This can be done using a separate Thread with read (which is a blocking method):

这可以使用带有 read 的单独线程(这是一种阻塞方法)来完成:

Thread t = new Thread() {
  public void run() {
    InputStream is = clientSocket.getInputStream();
    byte[] buffer = new byte[1024];
    int read;

    while(true) {
      read = is.read(buffer);
      onClientRead(clientSocket, read);
    };
  }
};
t.start();

This is a "test way", try make a separete class for this Thread.

这是一种“测试方式”,尝试为此线程创建一个单独的类。