设计和实施网络协议的最佳做法是什么?

时间:2010-10-20 16:42:17

标签: networking tcp network-programming computer-science network-protocols

我第一次尝试通过TCP / IP实现一些网络协议。我设计了一个,但我不确定它是否有效。

设计

所以这是我的想法:在客户端打开与服务器的TCP / IP连接后,每次它想要发出请求时,首先它发送请求的大小,然后是一些分隔符(新行或空格),然后是实际的请求(在HTTP中使用相同的主体,我认为在大多数情况下使用这个想法)。

例如,如果客户端想要发送GET ASD,它实际上会发送7 GET ASD(假设该空间是分隔符)。

对于服务器端,每个客户端服务器都有缓冲区,用于保存传入的请求。每当它从客户端获得一些新的字符块时,服务器就会将它附加到相应的客户端缓冲区。之后,服务器将尝试获取请求的内容长度(在此示例中为7)并检查缓冲区的其余长度是否大于或等于它。如果是,服务器将获得请求的实际内容,处理并将其从缓冲区中删除。

实施

这一切都与协议设计有关,现在关于实际实现的一些注意事项:我认为这里的主要问题是有效地实现和管理缓冲区。

我认为大小为2 * MAX_SIZE_OF_ONE_REQUEST的缓冲区足以为一个客户端服务,因为服务器接收的块可以同时包含第一个请求的结束和第二个请求的开始。这是我的假设,如果我错了,我们需要更多或更少的空间请告诉我原因。

我认为有两种方法可以在缓冲区中存储请求:

  1. 每当服务器收到新的字符块时,服务器都会将其附加到缓冲区的右侧。一旦缓冲区包含完整请求,服务器将处理它并在缓冲区空间的开头向左移动所有剩余的缓冲区。

  2. 一些循环缓冲区,在处理请求之后不会在开始时移动缓冲区。

  3. 这是我对实现具有异步I / O的缓冲区的想法(服务器将使用epoll / kqueue / select来接收来自客户端的请求)。我认为如果服务器不会使用异步I / O与客户端进行通信,那么实现缓冲区将会简单得多。

    此外,我还没有确定服务器收到格式错误的请求时应该如何表现。它应该与客户关闭吗?

    也许我已经写了很多,但我真的对这个话题感兴趣,并希望尽可能多地学习。我认为有很多人喜欢我,所以关于这个主题的任何现实世界问题和解决它们的最佳实践都会非常有用.1。

2 个答案:

答案 0 :(得分:3)

您需要人类可读的协议吗?如果没有,那么我建议使用二进制文件,以x字节的命令长度开始,然后根据需要形成其余的消息;当然,如果您愿意,其余的消息可能是文本...恕我直言,这在服务器上更容易处理,因为您不需要扫描所有输入字节以确定消息何时结束。

由于您知道确定消息长度所需的(固定)字节数,因此可以忽略所有消息,直到消息长度为止。您(可能)具有合理的最大消息大小,因此可以在可容纳所有消息的缓冲区方面工作。这意味着您可以将读取累积到单个缓冲区中,直到您有完整的消息,没有复制,没有移动。获得完整的消息后,您可以通过此缓冲区进行处理并开始阅读新的缓冲区。引用计数缓冲区,它们可以在您使用完毕后返回池中。

要防止拒绝服务攻击,您的读取数据应该超时。 x中没有完整的消息,你断开连接。

格式错误的消息,您断开连接。恕我直言Postel有很多可以回答的问题;当你迂腐,人们得到正确的东西并且接受的东西时,恕我直言协议会更好......

邮件大小超出允许范围,断开连接。

我讨论了有关长度前缀和基于行(序列终止)协议的TCP消息帧问题herehere,尽管讨论的重点是我的免费可插拔服务器平台{{3}所以它可能对您有用,也可能没用。

老实说,这很容易。复杂的部分是设计实际的协议,允许客户端和服务器有效地交换问题空间...但是,一旦你进入更复杂的位,这一点就会导致有趣的问题......

答案 1 :(得分:3)

首先,我会检查RFC和ITU.T规范,了解执行您想要做的事情的协议。如果你找不到一个,你至少可以看到其他协议是如何设计的,并阅读其中的一些基本原理。

查看XDR或BER(ASN.1)以获取数据的二进制编码。有一些libs用于处理endiannes和对齐混乱。例如,在XDR opaque中包装每个数据包可以让您更有效地设计服务器(1个TCP前端模块,它将未处理的opaques发送给正确的处理程序,而不必知道每个数据包的含义)。

正如Len Holgate所提到的,请务必说明在特殊情况下应该发生什么(格式错误的数据包,没有响应)或者是否应该有任何保持活动的数据包?如果是这样,多久一次?应该有一些客户端 - 服务器协商。

哦,不要忘记在hello数据包中包含协议版本。使用“我的客户端应用程序说我不支持协议的第2版”获得问题票证要好于“某些客户端工作正常,但当我尝试接收数据集时,我得到的都是随机数!”。< / p>