栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

Java网络:事件化的Socket / InputStream

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java网络:事件化的Socket / InputStream

简短地说,不。

available()
是不可靠的(至少对我来说不是)。我建议
java.nio.channels.SocketChannel
Selector
和一起使用
SelectionKey
。该解决方案在某种程度上基于事件,但是比普通套接字更加复杂。

对于客户:

  1. 构造套接字通道(
    socket
    ),打开选择器(
    selector = Selector.open();
    )。
  2. 使用非阻塞
    socket.configureBlocking(false);
  3. 注册连接器选择器
    socket.register(selector, SelectionKey.OP_CONNECT);
  4. 连接
    socket.connect(new InetSocketAddress(host, port));
  5. 看看是否有新东西
    selector.select();
  6. 如果“新”表示成功连接,则为
    OP_READ
    ; 注册选择器。如果“新”指的是可用数据,则只需从套接字读取。

但是,为了使其异步,您需要设置一个单独的线程(尽管套接字被创建为非阻塞的,但无论如何该线程都会阻塞),以检查是否已到达某些线程。

对于服务器,这里有

ServerSocketChannel
您使用的服务器
OP_ACCEPT

供参考,这是我的代码(客户端),应给您提示:

 private Thread readingThread = new ListeningThread();  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;  } }  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);  } }  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    }   }  } }  public void start() {  // start a reading thread  if(!this.running) {   this.readingThread = new ListeningThread();   this.readingThread.start();  } }  public void close() {  this.close = true; }

对于服务器:

  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); }  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);  } }  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  } }

希望这可以帮助。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/414116.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号