一个TCP连接需要在两端进行哪些动作
Which actions need to be performed on both ends for a TCP connection
我不太明白 TcpListener
和 TcpClient
交流时一些功能是如何共享的。
假设下面的代码是运行(现在忽略同步):
服务器:
Dim server As New TcpListener(localAddr, port)
server.Start()
Dim client As TcpClient = server.AcceptTcpClient()
客户:
Dim client As New TcpClient
client.Connect(hostAddr, port)
连接成功。现在有两个 TcpClient
个实例——一个在服务器端,一个在客户端。但是,他们通过 TcpClient.GetStream()
.
共享相同的网络流
我有点困惑 — 当调用 server.AcceptTcpClient()
时,客户端是否将自身及其所有属性传递给服务器?
在此之后对 TcpClient
个实例中的任何一个有什么变化?当连接关闭时,我在两侧调用它:
client.GetStream.Close()
client.Close()
但是我在客户端上遇到 TcpClient.GetStream.Close()
的异常,它最近执行了这段代码,因为它告诉我客户端已经关闭(当上面的代码在双方没有完全同步时会发生这种情况).
.SendBufferSize
和 .ReceiveBufferSize
属性呢?我需要在连接的两端都设置吗?
希望有人可以通过解释 TcpClient/Listener
类 在通信过程中究竟如何工作来消除我的困惑 — 到目前为止,我还没有找到解释到底发生了什么的文档。
TCP 协议不知道TcpClient
是什么。这是一个.NET 概念。 TCP 根本不引用 .NET 概念。因此,不会通过网络发送任何对象。
唯一发送的是您明确写入的字节。
每一方都有自己的独立对象。双方都使用自己的 TcpClient
对象,该对象充当 TCP 连接的句柄。
client.GetStream.Close()
client.Close()
这不是正确的关机顺序。第一行相对于第二行是多余的,而且不完整。永远不要调用 Close。最好的方法是将客户端包装在 using
中。第二种最佳方法是在客户端调用 Dispose
。 BCL 中的 Close
方法是历史事件,应该忽略。在我看过的所有情况下,他们做的事情和 Dispose 做的一样。
不要触及缓冲区大小。它们控制内核使用多少内存来缓冲连接端的数据。内核能够自行管理它。
也不要查看代码中的缓冲区大小。它们毫无意义。也不要使用 DataAvailable
属性 因为如果它 returns false/0
这并不意味着没有数据可以读取。
Connected
属性不一定两边同步。如果网络出现故障,则无法进行同步。永远不要看Connected
属性。如果它说 true
下一个纳秒,它可能是 false
。因此不可能根据 属性 做出决定。你不需要测试任何东西。只需 Read/Write 并通过中止处理异常。
关于数据包,当你Write
时你没有发送数据包。 TCP 有一个无边界的字节流。内核在内部打包您的数据。您不需要将数据拆分为特定大小。只需使用相当大的缓冲区大小,例如 8K(或在快速网络上更大)。写入大小只是通过减少聊天来节省 CPU 时间(假设启用了唠叨)。
我不太明白 TcpListener
和 TcpClient
交流时一些功能是如何共享的。
假设下面的代码是运行(现在忽略同步):
服务器:
Dim server As New TcpListener(localAddr, port)
server.Start()
Dim client As TcpClient = server.AcceptTcpClient()
客户:
Dim client As New TcpClient
client.Connect(hostAddr, port)
连接成功。现在有两个 TcpClient
个实例——一个在服务器端,一个在客户端。但是,他们通过 TcpClient.GetStream()
.
我有点困惑 — 当调用 server.AcceptTcpClient()
时,客户端是否将自身及其所有属性传递给服务器?
在此之后对 TcpClient
个实例中的任何一个有什么变化?当连接关闭时,我在两侧调用它:
client.GetStream.Close()
client.Close()
但是我在客户端上遇到 TcpClient.GetStream.Close()
的异常,它最近执行了这段代码,因为它告诉我客户端已经关闭(当上面的代码在双方没有完全同步时会发生这种情况).
.SendBufferSize
和 .ReceiveBufferSize
属性呢?我需要在连接的两端都设置吗?
希望有人可以通过解释 TcpClient/Listener
类 在通信过程中究竟如何工作来消除我的困惑 — 到目前为止,我还没有找到解释到底发生了什么的文档。
TCP 协议不知道TcpClient
是什么。这是一个.NET 概念。 TCP 根本不引用 .NET 概念。因此,不会通过网络发送任何对象。
唯一发送的是您明确写入的字节。
每一方都有自己的独立对象。双方都使用自己的 TcpClient
对象,该对象充当 TCP 连接的句柄。
client.GetStream.Close()
client.Close()
这不是正确的关机顺序。第一行相对于第二行是多余的,而且不完整。永远不要调用 Close。最好的方法是将客户端包装在 using
中。第二种最佳方法是在客户端调用 Dispose
。 BCL 中的 Close
方法是历史事件,应该忽略。在我看过的所有情况下,他们做的事情和 Dispose 做的一样。
不要触及缓冲区大小。它们控制内核使用多少内存来缓冲连接端的数据。内核能够自行管理它。
也不要查看代码中的缓冲区大小。它们毫无意义。也不要使用 DataAvailable
属性 因为如果它 returns false/0
这并不意味着没有数据可以读取。
Connected
属性不一定两边同步。如果网络出现故障,则无法进行同步。永远不要看Connected
属性。如果它说 true
下一个纳秒,它可能是 false
。因此不可能根据 属性 做出决定。你不需要测试任何东西。只需 Read/Write 并通过中止处理异常。
关于数据包,当你Write
时你没有发送数据包。 TCP 有一个无边界的字节流。内核在内部打包您的数据。您不需要将数据拆分为特定大小。只需使用相当大的缓冲区大小,例如 8K(或在快速网络上更大)。写入大小只是通过减少聊天来节省 CPU 时间(假设启用了唠叨)。