问题标签 [socketchannel]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
java - SocketChannel 触发 isReadable() 但没有可读取的内容
我的 Android 应用程序出现了新问题。SocketChannel
告诉我它,但isReadable()
没有什么可读的。
我在onProgressUpdate
. 这是一个WebSocket
应用程序,所以我需要发送和接收握手。使用此 while 循环发送和接收握手。首先SelectionKey.isWriteable()
发送和握手,然后SelectionKey.isReadable()
读取和握手。但那SelectionKey.isReadable()
仍然是真的。现在调用正常的读取函数(不是readHandshake
)函数。但是没有什么可读的。这是我的读取功能的代码:
现在它陷入了无休止的while循环。remainingBytes 永远不会 < 0,因为没有要读取的内容,并且 bytesRead 保持为 0。
我的问题是为什么 isReadable 在没有什么可读的时候是真的?
java - Java NIO:如何知道 SocketChannel read() 何时通过非阻塞 I/O 完成
我目前正在使用非阻塞 SocketChannel (Java 1.6) 作为 Redis 服务器的客户端。Redis 直接通过套接字接受纯文本命令,由 CRLF 终止并响应类似,一个简单的示例:
发送:'PING\r\n'
RECV: '+乒乓球\r\n'
Redis 还可以返回大量回复(取决于您要求的内容),其中包含许多以 \r\n 结尾的数据部分,所有这些都作为单个响应的一部分。
我正在使用标准的while(socket.read() > 0) {//append bytes}循环从套接字读取字节并将它们重新组装成客户端的回复。
注意:我没有使用选择器,只是连接到服务器的多个客户端 SocketChannel,等待服务发送/接收命令。
我感到困惑的是 SocketChannel.read() 方法在非阻塞模式下的合同,具体来说,如何知道服务器何时完成发送并且我有整个消息。
我有一些方法可以防止返回过快并让服务器有机会回复,但我坚持的一件事是:
- read()是否有可能返回字节,然后在后续调用中不返回字节,但在另一个后续调用中再次返回一些字节?
基本上,如果我收到至少 1 个字节并最终read()返回 0,我是否可以相信服务器已完成对我的响应,然后我知道我已经完成了,或者服务器可能只是忙并且可能会喷出一些如果我等待并继续尝试更多字节?
如果即使在 read() 返回 0 字节后(在之前的成功读取之后)它仍然可以继续发送字节,那么我不知道如何判断服务器何时完成与我的对话,实际上我很困惑 java.io.*样式通信甚至会知道服务器何时“完成”。
正如你们所知,除非连接已死,否则 read 永远不会返回 -1 并且这些是标准的长期数据库连接,所以我不会在每个请求时关闭和打开它们。
我知道一个流行的回答(至少对于这些 NIO 问题)是看看 Grizzly、MINA 或 Netty——如果可能的话,我真的很想在采用一些 3rd 方依赖项之前了解这一切是如何在原始状态下工作的。
谢谢你。
奖金问题:
我最初认为阻塞 SocketChannel 将是解决此问题的方法,因为在我处理他们的命令并给他们回复之前,我真的不希望调用者做任何事情。
如果这最终是一个更好的方法,我有点困惑看到 SocketChannel.read() 阻塞,只要没有足够的字节来填充给定的缓冲区......没有逐字节读取所有内容我无法弄清楚这个默认行为实际上是如何使用的......我永远不知道从服务器返回的回复的确切大小,所以我对 SocketChannel.read() 的调用总是阻塞直到超时(此时我终于看到内容位于缓冲区中)。
我不清楚使用阻塞方法的正确方法,因为它总是挂断读取。
java - 无论 CyclicBarrier 如何,一个线程都过早停止
我知道以下代码可能看起来很粗俗,但我对这些东西很陌生,只是尝试了一切以使其正常工作..
问题:即使我正在使用(可能以错误的方式)一个 CyclicBarrier,一个 - 并且似乎总是相同的 - 线程过早停止并打印出他的向量,在这些“传入连接”消息中的 11 个中留下 1 个不存在. 我的循环的最后一次迭代可能存在严重错误,但我似乎无法找到确切的内容。现在程序只是循环等待处理最后一个连接。
为了
澄清,这里是使用的文件格式。配置包含客户端使用的主机名和端口,它们是线程,输入文件的行表示“此客户端向该客户端发送消息”或“此客户端将其逻辑时钟增加某个常数值”。
1 M 2 (M 表示发送消息)
2 M 3
3 M 4
2 L 7 (L 表示递增时钟)
2 M 1
...
127.0.0.1 9000
127.0.0.1 9001
127.0.0.1 9002
127.0.0.1 9003
...
java - SocketChannel 连接的 Java 问题
这是一个课堂作业,所以我需要提示而不是答案。
我有一个在四台虚拟 linux 机器上运行的进程。每个进程与它的两个邻居进行通信。每个进程使用
在启动时,进程 A 不会尝试连接到任何人。过程 B 确实
过程 C 对 B 做同样的事情;和 D 与 C。
接下来,我调用 selector.select 并遍历任何 selectedKeys。当我看到 key.isValid() && key.isAcceptable() 都为真时,我认为一个套接字正在尝试连接到我,我打电话
当我看到 key.isValid() && key.isConnectable() 都为真时,我认为有一个服务器可供我连接。我打电话
当我看到 key.isValid() && key.isReadable() 时,我读到了我收到的一条消息。
只要我按顺序启动进程:A、B、C、D,这个进程就可以工作。如果我只启动 B,它会在 finishConnect 语句中失败。
我阅读了文档,其中 isConnectable 测试此密钥的通道是否已完成或未能完成其套接字连接操作。isConnectable 怎么可能是真的,而我在 finishConnect 上失败了?
java - 在 Java 中写入 SocketChannel 意外重复
一段时间以来,我一直在尝试使用 NIO SocketChannels,但我对写入 SocketChannel 感到困惑。以下代码来自我的客户:
}
当我尝试向频道写信时,我的问题必须解决。每当这部分代码运行时,它都会循环无数次,在每次迭代期间将数据写出,而无需等待服务器处理它。当我用我的代码运行调试器时,服务器似乎能够赶上并处理传输(客户端不断重新发送请求,但至少服务器显示传输的字节)。但是,当代码按原样运行而没有任何强制延迟时,客户端代码运行了几十次,然后连接断开,而服务器似乎忽略了传输。这是我的服务器代码部分 - 请注意,它是从 Runnable 类运行的:
我知道这是很多代码,但此时我无法确定问题出在哪里。任何人都可以推断为什么客户端和服务器似乎无法通信,尽管如果我强制延迟传输会正常进行?
谢谢。
java - Java NIO 问题/对 isReadable 工作原理的误解
我发现除了简单的情况外,NIO 的文档记录最多。即便如此,我已经完成了教程和几次重构,最终退回到最简单的情况,但我仍然偶尔会通过读取 0 字节的 SocketChannel 来触发 isReadable。并非每次执行都会发生。
我曾经在一个单独的线程中从附加对象调用读取,并认为这可能是竞争条件,但我已经开始在选择器的线程中进行读取,但问题仍然存在。我想它可能是我的测试客户端,但我不确定什么会不一致地触发它,因为客户端套接字在收到服务器的响应之前不应该关闭。
因此,在包含的代码中,此代码段发送的“hello”消息每次都能像我预期的那样正常
在此之后,我偶尔会得到一个 0 长度的套接字通道。有时会从这个片段中得到正确的响应:
对此的任何见解将不胜感激,它正在慢慢杀死我。我已经尝试在这里找到答案,但似乎相关的一个问题并没有真正说明我的问题。
提前致谢!
下面的代码片段:
选择方法:
读取方法(忽略这里的一些愚蠢,这是从另一个线程中拉出来的)
客户端片段:
java - 爪哇;NIO - 从 SocketChannel 读取大量数据
我正在编写一个非常简单的网络库,将来可以用于我的其他项目。现在,我在处理阅读操作时遇到了麻烦。我有一个类负责处理来自 SocketChannels 的事件,它还包含输入和输出缓冲区。要初始化缓冲区,您需要定义它的大小。所以默认情况下,所有缓冲区的大小都是 1024 字节。
我遇到的问题是,如果我读取一个大于 1024 字节的数据包,我会得到一个异常。这可以通过默认分配更大的缓冲区(例如 2048 字节,而不是 1024 字节)来解决,但这似乎是一种简单的方法,我特别不喜欢这种解决方案。
我想出的解决方案是创建一个非常大的直接静态缓冲区(它是 Short.MAX_VALUE 大)。来自 SocketChannels 的所有数据都将被读入大缓冲区,然后复制到较小的缓冲区中(如果缓冲区无法容纳数据,则会扩展缓冲区)。
我只是担心不断清除数据并将其放入大型“结转”缓冲区可能会产生大量成本。如果有类似 SocketChannel.available() 的东西,我会喜欢它,但唯一最接近的替代方法是 Socket.getInputStream().available(),但该方法会阻塞。这样,如果可用数据多于缓冲区可以容纳的数据,我将扩展输入缓冲区(而不是大缓冲区)。不幸的是,我不能——所以我能想到的唯一解决方案就是我上面提到的那个。
我来这里是想问...你们中的任何一个聪明人有可能更好地解决这个问题吗?另外,我不想使用外部库——这只是个人喜好。
提前非常感谢!
我很抱歉。和一位亲密的朋友交谈后,我意识到一开始没有问题。解释很长,我就不解释了。我很抱歉。
发帖人注意:请永远不要删除问题文本。它为其他人提供指导。
android - 使用非阻塞 SocketChannel,附属的 Socket 是否阻塞?
我正在开发一个 Android 应用程序,尝试从套接字上的一个线程进行非阻塞写入,同时在另一个线程上进行阻塞读取。我正在查看 SocketChannel 文档并试图弄清楚 configureBlocking 究竟做了什么。具体来说,如果我有一个非阻塞的 SocketChannel,并且我使用 socketChannel.socket() 访问附属的 Socket,那么该 Socket 在某种程度上也是非阻塞的吗?还是阻塞了?
换句话说,我可以通过一个非阻塞的SocketChannel作为非阻塞方向,而使用附属的Socket作为另一个方向,从而获得一个阻塞方向和一个非阻塞方向的效果吗?
java - ReadableByteChannel 挂起读取(字节缓冲区)
我正在使用 java 1.6 开发即时通讯工具。IM 使用多线程 - 主线程、接收和 ping。对于 tcp/ip 通信,我使用了 SocketChannel。从服务器接收更大的包裹似乎存在问题。服务器而不是一个发送几个包,这就是问题开始的地方。每前 8 个字节说明包的类型和大小。这就是我管理阅读的方式:
在测试期间一切都很好,直到我登录我的帐户并导入我的好友列表。我向服务器发送状态请求,他将 80 个联系人中的大约 10 个发回给我。所以我想出了这样的事情:
并且每个 readStuff() 和 readDescription() 都在检查缓冲区中剩余字节的每个参数大小:
并且 Receiver.receiver.read() 是:
所以应用程序被午餐,记录,然后发送联系人。服务器将我的列表中的一部分发回给我。但是在readInStatus(ByteBuffer headBuffer)方法中,我尝试强制列表的其余部分。现在有趣的部分 - 一段时间后它到达Receiver.receiver.read()并且在bytes = readChannel.read(bb)上它只是停止了,我不知道为什么,即使经过一段时间也没有错误没有什么,我出去了的想法。我整整一周都在与解决方案作斗争,但我没有得到任何解决方案。我将不胜感激任何建议。谢谢。
感谢您的回复。是的,我正在使用阻塞 SocketChannel,我尝试了非阻塞,但它变得疯狂并且失控,所以我跳过了这个想法。关于我期望的字节 - 这有点奇怪,因为它只给了我一次大小,但它的第一部分的大小不是整个包,其他部分根本不包含标题字节。我无法预测它会有多少字节,原因是 - 容量为 255 字节的描述。这正是我在以下位置创建变量好友的原因:public synchronized void readInStatus(ByteBuffer headBuffer)
这基本上是我的好友列表的长度,在读取每个字段之前,我正在检查是否还有足够的字节,如果没有的话,我会read(). 但是描述之前的最后一个字段是带有传入描述长度的整数。但在完成某些处理之前,无法确定包裹的长度。@robert 你认为我应该在那种情况下再次尝试切换到非阻塞 SocketChannel 吗?
java - Java NIO:transferFrom 直到流结束
我在玩 NIO 库。我正在尝试侦听端口 8888 上的连接,一旦连接被接受,就将该通道中的所有内容转储到somefile
.
我知道如何使用ByteBuffers
,但我想让它与据称超级高效的FileChannel.transferFrom
.
这就是我得到的:
所以,我的问题是:我如何表达“transferFrom
在到达流结束之前的某个频道”?
编辑:将 1024 更改为 BUF_SIZE,因为使用的缓冲区大小与问题无关。