gpt4 book ai didi

c# - C#中的套接字编程入门-最佳实践

转载 作者:IT王子 更新时间:2023-10-29 04:06:26 26 4
gpt4 key购买 nike

我在这里看到了许多关于套接字的资源。我相信他们没有一个涵盖我想知道的细节。在我的应用程序中,服务器执行所有处理,并定期向客户端发送更新。

这篇文章的目的是涵盖开发套接字应用程序并讨论最佳实践时所需的所有基本思想。这是几乎所有基于套接字的应用程序都将看到的基本内容。

1-绑定(bind)和监听套接字

我正在使用以下代码。它在我的机器上运行良好。将其部署在真实服务器上时,是否需要注意其他事项?

IPHostEntry localHost = Dns.GetHostEntry(Dns.GetHostName());
IPEndPoint endPoint = new IPEndPoint(localHost.AddressList[0], 4444);

serverSocket = new Socket(endPoint.AddressFamily, SocketType.Stream,
ProtocolType.Tcp);
serverSocket.Bind(endPoint);
serverSocket.Listen(10);

2- 接收数据

我已经使用了255个字节的字节数组。因此,当我接收到超过255个字节的数据时,我需要调用receive方法,直到获得完整的数据,对吗?一旦获得了完整的数据,我需要追加到目前为止接收到的所有字节,以获取完整的消息。那是对的吗?还是有更好的方法?

3- 发送数据并指定数据长度

由于TCP中无法找到要接收的消息的长度,因此我计划将长度添加到消息中。这将是数据包的第一个字节。因此,客户端系统知道可以读取多少数据。

还有其他更好的方法吗?

4- 关闭客户端

客户端关闭时,它将向服务器发送一条消息,指示关闭。服务器将从其客户端列表中删除客户端详细信息。以下是客户端断开套接字使用的代码(消息部分未显示)。
client.Shutdown(SocketShutdown.Both);
client.Close();

有什么建议或问题吗?

5- 关闭服务器

服务器向所有客户端发送消息,指示关闭。每个客户端在收到此消息时都将断开套接字。客户端将关闭消息发送到服务器并关闭。服务器收到来自所有客户端的关闭消息后,将断开套接字的连接并停止监听。在每个客户端套接字上调用Dispose以释放资源。那是正确的方法吗?

6- 未知客户端断开连接

有时,客户端可能会在不通知服务器的情况下断开连接。我要解决的计划是:当服务器向所有客户端发送消息时,请检查套接字状态。如果未连接,请从客户端列表中删除该客户端,然后关闭该客户端的套接字。

任何帮助将是巨大的!

最佳答案

由于这是“入门”,因此我的答案将停留在简单的实现方式上,而不是高度可扩展的实现方式。最好在使事情变得更复杂之前先对简单的方法感到满意。

1-绑定(bind)和监听
您的代码对我来说似乎很好,我个人使用:

serverSocket.Bind(new IPEndPoint(IPAddress.Any, 4444));

而不是走DNS路由,但我认为这两种方式都不存在真正的问题。

1.5-接受客户端连接
仅出于完整性的考虑而提及此问题...我假设您正在这样做,否则您将无法进行第2步。

2-接收数据
除非您可以期望所有服务器消息最多为255个字节,否则我将使缓冲区略大于255个字节。我认为您想要一个可能大于TCP数据包大小的缓冲区,这样就可以避免进行多次读取来接收单个数据块。

我会说选择1500个字节应该没问题,甚至对于一个很好的整数也可以选2048个字节。

或者,也许您可​​以避免使用 byte[]存储数据片段,而是将服务器端客户端套接字包装在 NetworkStream中,并包装在 BinaryReader中,这样您就可以从套接字读取消息透明性的组件,而不必担心缓冲区大小。

3-发送数据并指定数据长度
您的方法可以很好地工作,但显然确实需要在开始发送数据包之前很容易计算出数据包的长度。

或者,如果您的消息格式(其组成部分的顺序)以某种方式设计,以便客户端可以随时确定后面是否应该有更多数据(例如,代码0x01表示next将是一个int且一个字符串,代码0x02表示下一个将是16个字节,依此类推,等等)。结合客户端上的 NetworkStream方法,这可能是一种非常有效的方法。

为了安全起见,您可能需要添加对收到的组件的验证,以确保仅处理理智的值。例如,如果收到长度为1TB的字符串的指示,则可能是某处有数据包损坏,并且关闭连接并强制客户端重新连接并“重新开始”可能更安全。如果发生意外故障,此方法可为您提供很好的万能行为。

4/5-关闭客户端和服务器
就我个人而言,我只选择 Close而没有更多消息。当连接关闭时,您将不得不在连接的另一端收到任何阻塞的读/写异常。

由于无论如何您都必须迎合“未知的断开连接”才能获得可靠的解决方案,因此断开连接更复杂通常是没有意义的。

6-未知的断开连接
我什至都不相信套接字状态...连接可能会在客户端/服务器之间的某个路径上的某个位置死掉,而不会引起客户端或服务器的注意。

告诉连接已意外终止的唯一保证方法是下次尝试沿连接发送消息时。到那时,如果连接出现任何问题,您将始终得到一个异常,指示失败。

结果,检测所有意外连接的唯一防呆方法是实现“ping”机制,理想情况下,客户端和服务器将定期向另一端发送消息,该消息仅导致指示消息的响应。收到“ping”。

要优化不必要的ping,您可能需要一种“超时”机制,该机制仅在设置的时间内没有收到另一端的其他流量时才发送ping(例如,服务器的使用时间已超过x秒,则客户端会发送ping命令以确保连接未在没有通知的情况下终止)。

更高级的
如果要实现高可伸缩性,则必须针对所有套接字操作(接受/发送/接收)研究异步方法。这些是“开始/结束”变体,但使用起来要复杂得多。

我建议您不要尝试此操作,直到您安装并运行了简单版本。

还要注意,如果您不打算扩展规模而不是几十个客户,那么这实际上将不是问题。仅当您打算扩展到成千上万个已连接的客户端而又不让服务器彻底中断时,异步技术才真正是必需的。

我可能已经忘记了很多其他重要建议,但这应该足以使您从开始一个相当健壮和可靠的实现

关于c# - C#中的套接字编程入门-最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1162950/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com