-1

everybody. There was a problem, I was thinking for a long time. I can conntect other host by "socket". I used "socketServer.accept()". When there was someone calling me, I can know. Here is the code.

while (this.connState != 0) {
        Socket client = null;
        try {
            client = this.serverSocket.accept();
        } catch (IOException e) {
            e.printStackTrace();
        }
}

And then I can get the 'stream', and get my data.

But I don't want to get it by that way.

I want to tell the OS that what I will do when I get my data. If it is possible, I don't have to check the socket every time. Can I do that? Is there any interface or event I can use?

Smoke
  • 31
  • 3

3 Answers3

1

You can remove the while() loop; in that case, the server will simply accept a single connection and terminate.

This isn't a "busy loop." ServerSocket.accept() will block until a connection is being made.

As explained in another answer, you can use NIO. Another option is Akka as explained in "Using TCP" (no, I'm not copy&pasting ~200 lines of code from the Akka docs here).

While the setup of Akka looks insanely expensive, the rewards is a powerful system to slice&dice your incoming connections turn them into messages, route them through actors which either return results or pass the message on to other actors.

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
0

Fortunately, Java NIO supports this : http://docs.oracle.com/javase/7/docs/api/java/nio/channels/AsynchronousServerSocketChannel.html

Heres a useful example which doesnt use (error-prone) loops : http://www.java2s.com/Tutorials/Java/Java_Network/0080__Java_Network_Asynchronous_Socket_Channels.htm

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.nio.charset.Charset;
public class Main {
  public static void main(String[] args) throws Exception {
    AsynchronousServerSocketChannel server = AsynchronousServerSocketChannel
        .open();/*  ww w . j av a 2s. c om*/
    String host = "localhost";
    int port = 8989;
    InetSocketAddress sAddr = new InetSocketAddress(host, port);
    server.bind(sAddr);
    System.out.format("Server is listening at %s%n", sAddr);
    Attachment attach = new Attachment();
    attach.server = server;
    server.accept(attach, new ConnectionHandler());
    Thread.currentThread().join();
  }
}
class Attachment {
  AsynchronousServerSocketChannel server;
  AsynchronousSocketChannel client;
  ByteBuffer buffer;
  SocketAddress clientAddr;
  boolean isRead;
}

class ConnectionHandler implements
    CompletionHandler<AsynchronousSocketChannel, Attachment> {
  @Override
  public void completed(AsynchronousSocketChannel client, Attachment attach) {
    try {
      SocketAddress clientAddr = client.getRemoteAddress();
      System.out.format("Accepted a  connection from  %s%n", clientAddr);
      attach.server.accept(attach, this);
      ReadWriteHandler rwHandler = new ReadWriteHandler();
      Attachment newAttach = new Attachment();
      newAttach.server = attach.server;
      newAttach.client = client;
      newAttach.buffer = ByteBuffer.allocate(2048);
      newAttach.isRead = true;
      newAttach.clientAddr = clientAddr;
      client.read(newAttach.buffer, newAttach, rwHandler);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  @Override
  public void failed(Throwable e, Attachment attach) {
    System.out.println("Failed to accept a  connection.");
    e.printStackTrace();
  }
}

class ReadWriteHandler implements CompletionHandler<Integer, Attachment> {
  @Override
  public void completed(Integer result, Attachment attach) {
    if (result == -1) {
      try {
        attach.client.close();
        System.out.format("Stopped   listening to the   client %s%n",
            attach.clientAddr);
      } catch (IOException ex) {
        ex.printStackTrace();
      }
      return;
    }

    if (attach.isRead) {
      attach.buffer.flip();
      int limits = attach.buffer.limit();
      byte bytes[] = new byte[limits];
      attach.buffer.get(bytes, 0, limits);
      Charset cs = Charset.forName("UTF-8");
      String msg = new String(bytes, cs);
      System.out.format("Client at  %s  says: %s%n", attach.clientAddr,
          msg);
      attach.isRead = false; // It is a write
      attach.buffer.rewind();

    } else {
      // Write to the client
      attach.client.write(attach.buffer, attach, this);
      attach.isRead = true;
      attach.buffer.clear();
      attach.client.read(attach.buffer, attach, this);
    }
  }

  @Override
  public void failed(Throwable e, Attachment attach) {
    e.printStackTrace();
  }
}

You can prevent the main-thread from exiting with AsynchronousChannelGroup : https://stackoverflow.com/a/9448743/351861

Community
  • 1
  • 1
specializt
  • 1,913
  • 15
  • 26
0

Your question is not very clear, but I wonder if you are talking about a reactive programming approach.

With a tool like Akka, you can write a handler that the system calls when data is received. It handles a lot of the low level details like threading and sockets. You just write the code that says what to do when data is received.

Akka's networking capabilities are highly scalable, built on Java's "new" I/O (NIO) libraries, which can be used in a non-blocking, selector-based mode. (Akka uses Netty, which is built on these lower level NIO packages, for its remote message dispatch capability; I think Akka's networking packages might use Netty too.)

erickson
  • 265,237
  • 58
  • 395
  • 493