Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在服务器端或客户端的JavaNIOSocket过程中,套接字连接准备好发送数据了吗?_Java_Sockets_Tcp - Fatal编程技术网

在服务器端或客户端的JavaNIOSocket过程中,套接字连接准备好发送数据了吗?

在服务器端或客户端的JavaNIOSocket过程中,套接字连接准备好发送数据了吗?,java,sockets,tcp,Java,Sockets,Tcp,我正在使用JavaNIO,这是我第一次设置一个可用的TCP连接(到目前为止我只做过UDP,很久以前还做过一个简单的TCP测试程序) 现在,我不确定在什么时候可以可靠地开始向客户端发送数据,以便客户端知道另一端有活动连接(假设没有出现问题) 假设一切都是非阻塞的 客户: 1) 打开不带绑定的新套接字通道,以便将其设置为异步 s = SocketChannel.open() 2) 将其设置为非阻塞 s.configureBlocking(false) 我们需要绑在这里吗?或者,这仅仅是为了我

我正在使用JavaNIO,这是我第一次设置一个可用的TCP连接(到目前为止我只做过UDP,很久以前还做过一个简单的TCP测试程序)

现在,我不确定在什么时候可以可靠地开始向客户端发送数据,以便客户端知道另一端有活动连接(假设没有出现问题)


假设一切都是非阻塞的

客户:

1) 打开不带绑定的新套接字通道,以便将其设置为异步

s = SocketChannel.open()
2) 将其设置为非阻塞

s.configureBlocking(false)
  • 我们需要绑在这里吗?或者,这仅仅是为了我们想引用一个本地端口
3) 尝试连接到正在侦听的服务器

s.connect(someAddr)
  • 如果返回true,javadocs表示连接已建立。这是否意味着我不需要调用finishConnect()?从我读到的内容来看,这是针对本地连接的,但它没有指定远程连接是否可能立即返回true

  • 这是客户端向服务器发送SYN的地方吗


服务器:

4) 服务器通过某个
服务器socketchannel.accept()
获取传入连接,我们假设该连接是非阻塞的,并在本例中假装它返回一个有效的套接字对象(且不为null)

  • 这是否意味着一旦服务器获得连接,它就会接受连接(假设一切正常)并发回SYN-ACK

客户:

5) 客户端现在是否调用
finishConnect()

  • 客户端何时知道何时继续调用finishConnect()?从步骤(3)调用
    s.connect(…)
    后,我是否立即循环X秒

  • 这是它发送ACK的时候吗?我应该循环X秒直到它返回真值。。。如果“半成型连接”由于出现问题而在X秒内没有响应,则将其杀死

  • s.isConnected()
    是否为后续步骤(3)中的connect()返回true,或finishConnect()返回true


我不确定我是否正确地执行了此操作,而且我也不确定在什么情况下服务器发送或客户端发送是安全的。。。服务器是在(4)位,客户端是在(5)位

我是否需要让客户端在连接到服务器后发送心跳数据包,以便我的应用程序知道可以开始发送数据?我不知道服务器如何知道它已完全连接,因为我看不到服务器如何知道何时完成最终确认。。。除了客户端知道已建立连接并发送某种“第一个数据包”数据之外

服务器知道的唯一方法是,我是否能够以某种方式确定它何时收到ACK数据包,但我目前看不到Java让我知道的方法

注意:我可能缺少知识,我可能说了一些不正确的东西,如果你能指出他们错在哪里,我将非常高兴更新我的帖子,使它实际上是正确的

指导我了解/创建此帖子的链接:


注意:我已经使用socket而不是socketchannels完成了socket编程。这个答案是基于阅读socketchanneljavadoc,了解SocketChannel在幕后使用套接字并熟悉套接字

根据javadoc,如果connect()返回true,则连接已建立,您不需要调用finishConnect()。将finishConnect()视为检查连接建立状态的一种方法,而不是执行建立连接所需的任何操作的函数

在服务器上,如果accept()返回SocketChannel,则已从客户端接收到连接尝试。来自服务器的SYN ACK很可能已经发送,尽管Java文档故意没有指定这一点,以允许将来进行优化。Java很可能认为该连接是“已建立”的,不过您可以调用finishConnect()来确保;Java可能会等到服务器收到客户机的ACK后才考虑完全建立连接。注意,Javadoc指定返回的SocketChannel最初将处于阻塞模式,即使ServerSocketChannel处于非阻塞模式


在客户端,只要connect()或finishConnect()返回true,就可以开始发送数据。在服务器端,当finishConnect()返回true时,您当然可以开始发送数据;对finishConnect()的调用可能是多余的,accept()返回一个具有已建立连接的SocketChannel-这就是我编写它的方式-但我没有使用足够的SocketChannels来确定。在建立连接期间,您不需要发送心跳数据包,这样做可能会浪费精力,因为TCP协议本身处理所有与连接相关的事情,包括三方握手(SYN、SYN-ACK、ACK)要建立连接。

您需要使用选择器等待连接并接受事件

NIO没有那么难。但是Java的NIOAPI有点太难了。享受折磨自己的乐趣:)


JavaAPI调用和TCP握手步骤之间的精确映射不是很清楚。然而,我会在下面的模型中考虑它(如果它与现实中发生的事情不完全一样,那也没什么大不了的)

connect()
--同步-->
我们需要绑在这里吗?或者,这仅仅是为了我们想引用一个本地端口

您不需要绑定客户端
SocketChannel

s.connect(someAddr)
如果返回true,javadocs表示连接已建立。这是否意味着我不需要调用
finishConnect()

s.connect(someAddr)