java - 具有多个连接但只有一个线程的 ServerSocket
问题描述
我正在尝试为单线程物理产品编写模拟器。它接受一个长期连接,而任何其他连接都会收到一条错误消息(在同一个线程中)。
我知道我可以将 java.net 与两个线程一起使用:
- 线程 1 - 在端口 XXXX 上启动 ServerSocket 并等待 accept()。为第一个连接创建一个 Socket 和 Thread #2,并为其他连接产生一个错误消息。
- 线程 2 - 处理 Socket IO。
但是我怎么能用一个线程来做到这一点,所以它的行为更像物理产品(即重复尝试连接会使线程无法处理第一个连接)?
尽量不使用第三方库,但如果这是唯一的选择,可以这样做。
谢谢!
解决方案
不幸的是,接受传入连接的阻塞方法是常见java.net.ServerSocket
的也是唯一的功能。java.nio.channels.ServerSocketChannel
但是,该java.nio
包具有许多其他类和方法,可通过多路复用打开的通道在单个线程中处理 I/O 操作。
这种方法仍然会强制使用专用线程来接受ServerSocketChannel
,但您可以在单个线程中处理每个接受的连接。
相比之下,该ServerSocket
方法需要为每个新连接一个新线程。
假设您使用 a 连接 100 个客户端,ServerSocket
那么您最终将获得 101 个线程。使用 aServerSocketChannel
您最终可能只使用 2 个线程。
仍然编程通常是在复杂性/灵活性和性能之间进行权衡。所以记住这一点。
我能想到的一个可能的解决方案可能如下所示:
public static void main( String[] args ) throws IOException
{
int portNr = 8080;
ExecutorService es = Executors.newSingleThreadExecutor();
ChannelHandler ch = new ChannelHandler();
es.execute( ch );
// Starting server:
ServerSocketChannel serv = ServerSocketChannel.open();
// Bind socket to Port
serv.socket().bind(new InetSocketAddress(portNr));
while( serverAlive )
{
ch.addChannel(serv.accept());
}
serv.close();
}
您实际处理新添加的方式SocketChannel
取决于您的应用程序。方法也是如此ChannelHandler#addChannel
。
推荐阅读
- java - 无法删除 SD 卡上的文件
- ionic2 - 减少 ionic 2 中的闪屏和白屏总时间
- django - 在外键下拉列表中显示其所有依赖模型的值的总和
- html - 没有边距的 div 中不包含的文本:0 自动
- python - 列表追加替换先前附加的值
- android - 如何将 LinearGradient 用于反应选项卡导航器选项卡
- syntax-error - 如何查看为什么某个文件列在 vivado 的“语法错误文件”中
- android - Camera2 - 获取静止捕获位图的最有效方法
- android - 谷歌日历 API 错误?
- android - 画布覆盖的 textview 制动图像处理