Java Network: Improvised socket / InputStream

I'm implementing an event - oriented layer on a java socket. I wonder if there is a way to determine whether there is data to be read

My normal method is to read the buffer from the socket and call the callback provided when the buffer is filled with a fixed number of bytes (0 if the callback needs to be triggered every time it arrives), but I suspect that Java is already buffering me

Is the available () method of InputStream reliable? Should I read only () and do my own buffering on the socket? Or is there another way?

Solution

Soon, No Available () is unreliable (at least not for me) I recommend using Java. Net that connects to the selector and selectionkey nio. channels. socketChannel. This solution is somewhat event - based, but more complex than ordinary sockets

For customers:

>Construct a socket channel (socket) and open a selector (selector = selector. Open();). > Use non blocking socket configureBlocking(false); > Register selector socket for socket connection register(selector,SelectionKey.OP_CONNECT); > Connect socket Connect (New inetsocketaddress (host, port)); > See if there is a new selector select(); > If "new" indicates that the connection is successful, the selector OP is registered_ READ; If "new" refers to available data, just read it from the socket

However, in order to make it asynchronous, you need to set up a separate thread (although the socket is created as non blocking, the thread will still block), which will check whether something has been reached

For servers with serversocketchannel, you can use Op_ ACCEPT.

As a reference, this is my code (client). I should give you a hint:

private Thread readingThread = new ListeningThread();

 /**
  * Listening thread - reads messages in a separate thread so the application does not get blocked.
  */
 private class ListeningThread extends Thread {
  public void run() {
   running = true;
   try {
    while(!close) listen();
    messenger.close();
   }
   catch(ConnectException ce) {
    doNotifyConnectionFailed(ce);
   }
   catch(Exception e) {
//    e.printStackTrace();
    messenger.close();
   }
   running = false;
  }
 }

 /**
  * Connects to host and port.
  * @param host Host to connect to.
  * @param port Port of the host machine to connect to.
  */
 public void connect(String host,int port) {
  try {
   SocketChannel socket = SocketChannel.open();
   socket.configureBlocking(false);
   socket.register(this.selector,SelectionKey.OP_CONNECT);
   socket.connect(new InetSocketAddress(host,port));
  }
  catch(IOException e) {
   this.doNotifyConnectionFailed(e);
  }
 }

 /**
  * Waits for an event to happen,processes it and then returns.
  * @throws IOException when something goes wrong.
  */
 protected void listen() throws IOException {
  // see if there are any new things going on
  this.selector.select();
  // process events
  Iterator<SelectionKey> iter = selector.selectedKeys().iterator();
  while(iter.hasNext()) {
   SelectionKey key = iter.next();
   iter.remove();
   // check validity
   if(key.isValid()) {
    // if connectable...
    if(key.isConnectable()) {
     // ...establish connection,make messenger,and notify everyone
     SocketChannel client = (SocketChannel)key.channel();
     // Now this is tricky,registering for OP_READ earlier causes the selector not to wait for incoming bytes,which results in 100% cpu usage very,very fast
     if(client!=null && client.finishConnect()) {
      client.register(this.selector,SelectionKey.OP_READ);
     }
    }
    // if readable,tell messenger to read bytes
    else if(key.isReadable() && (SocketChannel)key.channel()==this.messenger.getSocket()) {
     // read message here
    }
   }
  }
 }

 /**
  * Starts the client.
  */
 public void start() {
  // start a reading thread
  if(!this.running) {
   this.readingThread = new ListeningThread();
   this.readingThread.start();
  }
 }

 /**
  * Tells the client to close at nearest possible moment.
  */
 public void close() {
  this.close = true;
 }

For servers:

/**
  * Constructs a server.
  * @param port Port to listen to.
  * @param protocol Protocol of messages.
  * @throws IOException when something goes wrong.
  */
 public ChannelMessageServer(int port) throws IOException {
  this.server = ServerSocketChannel.open();
  this.server.configureBlocking(false);
  this.server.socket().bind(new InetSocketAddress(port));
  this.server.register(this.selector,SelectionKey.OP_ACCEPT);
 }

 /**
  * Waits for event,then exits.
  * @throws IOException when something goes wrong.
  */
 protected void listen() throws IOException {
  // see if there are any new things going on
  this.selector.select();
  // process events
  Iterator<SelectionKey> iter = selector.selectedKeys().iterator();
  while(iter.hasNext()) {
   SelectionKey key = iter.next();
   // do something with the connected socket
   iter.remove();
   if(key.isValid()) this.process(key);
  }
 }

 /**
  * Processes a selection key.
  * @param key SelectionKey.
  * @throws IOException when something is wrong.
  */
 protected void process(SelectionKey key) throws IOException {
  // if incoming connection
  if(key.isAcceptable()) {
   // get client
   SocketChannel client = (((ServerSocketChannel)key.channel()).accept());
    try {
     client.configureBlocking(false);
     client.register(this.selector,SelectionKey.OP_READ);
    }
    catch(Exception e) {
     // catch
    }
  }
  // if readable,tell messenger to read
  else if(key.isReadable()) {
  // read
  }
 }

I hope this will help

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>