English 中文(简体)
设计和实施网络协议的最佳实践是什么?
原标题:What are best practices of designing and implementing Network Protocols?

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

设计

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

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

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

实施

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

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

我认为有两种方法可以将请求存储在缓冲区中,直到它们得到服务:

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

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

这是我关于实现异步I/O缓冲区的想法(服务器将使用epoll/kqueue/select来接收来自客户端的请求)。我认为若服务器不使用异步I/O和客户端通信,那个么实现缓冲区就会简单得多。

此外,我还没有决定服务器在接收到格式错误的请求时应该如何操作。是否应该关闭与客户端的连接?

也许我写了很多东西,但我对这个话题很感兴趣,想尽可能多地学习。我想有很多人和我一样,所以任何关于这个话题的现实世界问题以及解决这些问题的最佳实践都会非常有帮助。

问题回答

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

由于您知道确定消息长度所需的(固定)字节数,因此可以忽略所有消息,直到它们变长为止。您(可能)有一个合理的最大消息大小,因此可以使用可以容纳所有消息的缓冲区。这意味着您可以将读取累积到单个缓冲区中,直到您得到完整的消息为止,不需要复制,也不需要移动。一旦您有了一个完整的消息,您就可以传递这个缓冲区进行处理,并开始读取新的消息。引用计数缓冲区,当您使用完它们时,它们可以返回到池中。

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

消息格式不正确,请断开连接。国际海事组织Postel有很多问题需要回答;当你迂腐地认为人们做得对,接受得少时,IMHO协议会更好。。。

消息大小大于您允许的大小,则断开连接。

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

老实说,这是最容易的一点。复杂的部分是设计实际的协议,使客户端和服务器能够有效地就问题空间进行对话。。。然而,一旦你进入更复杂的部分,这一点的错误可能会导致有趣的问题。。。

首先,我会检查RFC和ITU-T规范,以找到一个可以做你想做的事情的协议。如果你没有找到,你至少可以看看其他协议是如何设计的,并阅读它背后的一些原理。

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

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

哦,别忘了在hello数据包中包含协议版本。收到“我的客户端应用程序说我不支持协议的第2版”的问题通知单比“有些客户端运行良好,但当我试图接收数据集时,我得到的都是随机数!”要好。





相关问题
C# Networking API s [closed]

Lately I ve been looking for a good networking API i could possibly use and/or reference some of the code within, but i have mere luck searching for some on Google/Bing. Hopefully somebody here has ...

Listen to a port that is in use [duplicate]

Possible Duplicate: Get connecting IP from specified ports that using by other program. If a port is used by a program, is there any way I can listen that port and get the connected IP on that ...

Twisted Spread suitable for multiplayer racing sim?

Do you think that Twisted Spread may be suitable (in terms of performance) for a multiplayer racing simulator? The rest of the application is based on Python-Ogre. Can Perspective Broker run upon (...

Optimizing a LAN server for a game

I m the network programmer on a school game project. We want to have up to 16 players at once on a LAN. I am using the Server-Client model and am creating a new thread per client that joins. ...

multicast ip address - blocked in call to recvfrom

i am writing a simple multicast application. i intend to run it on localhost. i have done the following: char *maddr; . . . sendfd = socket(...); struct sockaddr_in sasend; sasend.sin_family = ...

Java HTTPAUTH

我试图把桌面应用程序连接起来,我是同D.icio.us api @ Delicious Alan书写的,简单地向他们提供我的用户名和密码,并请他把书记上写给我......。

热门标签