在java中,有没有办法通过TCP / IP连接到其他主机而没有“while(true)”

时间:2015-03-24 16:05:43

标签: java sockets io

大家。有一个问题,我想了很久。 我可以通过" socket"来联系其他主机。我使用" socketServer.accept()"。当有人打电话给我时,我知道。这是代码。

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

然后我就可以获得'流'并获取我的数据。

但我不想以这种方式得到它。

我想告诉操作系统,当我获取数据时我会做什么。如果有可能,我不必每次都检查套接字。我能这样做吗?我可以使用任何界面或事件吗?

3 个答案:

答案 0 :(得分:1)

您可以删除while()循环;在这种情况下,服务器将只接受单个连接并终止。

这不是一个“忙碌的循环”。 ServerSocket.accept()将阻止,直到建立连接。

如另一个答案中所述,您可以使用NIO。另一种选择是Akka,如“Using TCP”中所述(不,我不是复制和粘贴来自Akka文档的200行代码)。

虽然Akka的设置看起来非常昂贵,但奖励是一个强大的系统,用于切片和切换你的传入连接将它们变成消息,通过演员路由它们,这些演员要么返回结果,要么将消息传递给其他演员。

答案 1 :(得分:0)

幸运的是,Java NIO支持这一点: http://docs.oracle.com/javase/7/docs/api/java/nio/channels/AsynchronousServerSocketChannel.html

这是一个不使用(容易出错)循环的有用示例: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();
  }
}

您可以阻止主线程退出AsynchronousChannelGrouphttps://stackoverflow.com/a/9448743/351861

答案 2 :(得分:0)

您的问题不是很清楚,但我想知道您是否在讨论反应式编程方法。

使用Akka,之类的工具,您可以编写系统在接收数据时调用的处理程序。它处理许多低级细节,如线程和套接字。您只需在收到数据时写下the code that says what to do

Akka的网络功能具有高度可扩展性,基于Java的“新”I / O(NIO)库构建,可用于非阻塞,基于选择器的模式。 (Akka使用Netty,构建在这些较低级别的NIO包上,因为它具有远程消息调度功能;我认为Akka的网络包也可能使用Netty。)