【问题标题】:Implements observer pattern on socket client server在套接字客户端服务器上实现观察者模式
【发布时间】:2014-05-25 13:07:26
【问题描述】:

每个客户端在连接到服务器后都会注册为观察者。 当任何客户端发生更改时,都会通知其他客户端。

我的问题是如何保持套接字连接?

我可以存储像Socket[] 这样的所有连接并每秒检查他们的InputStream 吗?

【问题讨论】:

  • 我大概知道它的逻辑。每个客户端在服务器上持有一个线程,那么1k个客户端可能导致服务器崩溃?我正在寻找单线程解决方案

标签: java sockets client-server observer-pattern


【解决方案1】:

我不知道我是否解决了你的问题......但我会试一试。

问题似乎是,您有 1 个 ServerSocket 和多个套接字(每个客户端一个),现在您希望获得有关这些套接字的活动的通知/通知。所以你打算遍历套接字列表?

关键字是非阻塞 I/O。搜索关键字“选择器”或“多路复用”。 我试着举一个简单的例子。

我构建了一个非常小的示例。但这是一个开始。这就是全部

package server;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.SelectorProvider;
import java.util.Iterator;
import java.util.Set;

public class Server {

public Server() throws IOException{
    Selector selector = SelectorProvider.provider().openSelector();
    ServerSocketChannel ssc = ServerSocketChannel.open().bind(new InetSocketAddress(9000));
    ssc.configureBlocking(false);       
    ssc.register(selector, 
              SelectionKey.OP_ACCEPT);  


    while(true) {

      int readyChannels = selector.select();

      if(readyChannels == 0) continue;


      Set<SelectionKey> selectedKeys = selector.selectedKeys();

      Iterator<SelectionKey> keyIterator = selectedKeys.iterator();

      while(keyIterator.hasNext()) {

        SelectionKey key = keyIterator.next();

        if(key.isAcceptable()) {
           System.out.println("acceptable");
           SocketChannel socketChan =  ((ServerSocketChannel)key.channel()).accept();
           socketChan.configureBlocking(false);
            socketChan.register(selector, SelectionKey.OP_READ);

        } else if (key.isConnectable()) {
            // a connection was established with a remote server.

        } else if (key.isReadable()) {
            System.out.println("Processing reading...");

            ByteBuffer buf = ByteBuffer.allocate(1024);
            int readedBytes = ((SocketChannel)key.channel()).read(buf);
            System.out.println("Readed: " + readedBytes);
            buf.flip();

            for(byte b : buf.array()) {
                System.out.print((char) b);
            }

        } else if (key.isWritable()) {
            // a channel is ready for writing
        }

        keyIterator.remove();
      }
    }
}

public static void main(String[] args) throws IOException {
    Server server = new Server();

}

}

我可以运行它,并通过端口 9000 上的 netcat 连接到它,并从那里发送消息。只需一个线程,拥有任意数量的客户端连接......

我使用了这个资源/示例

http://tutorials.jenkov.com/java-multithreaded-servers/thread-pooled-server.htmlhttp://docs.oracle.com/javase/7/docs/technotes/guides/io/example/index.html

【讨论】:

  • 感谢您的示例,但我无法弄清楚如何从您的代码中通知所有连接的客户端...selector.selectedKeys() 做什么?无限循环会压垮服务器吗?
  • 嵌套的while循环会在while(keyIterator.hasNext())处阻塞,所以没有忙等待 当然这只是一个小例子,不是为编写而构建的。但我认为解决这个问题并不是什么大问题。 selector.selectedKeys() 返回一组键。 Key 是一种令牌,它代表为选择器注册的 Chanel/Socket。这有点复杂。如果您阅读我使用的示例,最好是 tutorials.jenkov.com/java-multithreaded-servers/…docs.oracle.com/javase/7/docs/technotes/guides/io/example/…
猜你喜欢
  • 2015-09-16
  • 2012-11-15
  • 2020-04-06
  • 1970-01-01
  • 2011-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多