编写应用程序级协议的方法?

时间:2011-04-20 06:14:12

标签: custom-protocol communication-protocol data-formats

我正在用C#做一些简单的套接字编程。我试图通过从客户端控制台读取用户名和密码,将凭据发送到服务器,并从服务器返回身份验证状态来验证用户身份。基本的东西。我的问题是,我如何确保数据采用服务器和客户端期望的格式?

例如,以下是我在客户端上读取用户凭据的方法:

                Console.WriteLine("Enter username: ");
                string username = Console.ReadLine();
                Console.WriteLine("Enter plassword: ");
                string password = Console.ReadLine();

                StreamWriter clientSocketWriter = new StreamWriter(new NetworkStream(clientSocket));
                clientSocketWriter.WriteLine(username + ":" + password);
                clientSocketWriter.Flush();

这里我用客户端的冒号(或其他符号)分隔用户名和密码。在服务器上,我只需使用“:”作为标记拆分字符串。这有效,但似乎有些......不安全。不应该在客户端和服务器之间存在某种共享的分隔符令牌,所以我不必像这样硬编码吗?

这与服务器响应类似。如果身份验证成功,如何以客户端期望的格式发回响应?我只是发送一个“SUCCESS”或“AuthSuccessful = True / False”字符串吗?我如何确保客户端知道服务器发送数据的格式(除了将其硬编码到客户端之外)?

我想我要问的是如何设计和实现应用程序级协议。我意识到它对您的应用程序来说是独一无二的,但程序员通常使用的典型方法是什么?此外,您如何保持格式一致?我非常感谢有关这个问题的文章的一些链接。

4 个答案:

答案 0 :(得分:1)

而不是重新发明轮子。为什么不编写XML模式并发送和接收XML“文件”。

你的消息肯定会更长,但是使用千兆以太网和ADSL这些日子几乎不重要。你得到的是一个协议,其中所有的字符集问题,复杂的数据结构已经解决,加上一个令人尴尬的工具和库选择,以支持和简化您的开发。

答案 1 :(得分:0)

基本上,你正在寻找一个标准。 “关于标准的好处是有很多可供选择的”。选择一个并继续使用它,它比滚动自己更容易。对于这种特殊情况,请查看Apache“基本”身份验证,它将用户名和密码加入并对其进行base64编码,作为一种可能性。

答案 2 :(得分:0)

我使用了两种主要方法。

首先是基于ascii的协议。

基于Ascii的协议通常基于一组文本命令,这些命令终止于某些定义的分隔符(如回车符或分号或xml或json)。如果您的协议是基于命令的协议,其中没有大量数据来回传输,那么这是最好的方法。

FIND\r
DO_SOMETHING\r

它具有易于阅读和理解的优点,因为它是基于文本的。 缺点(可能不是问题但可能是)可能存在来自客户端和服务器的来回传输的未知数量的字节。因此,如果您需要确切地知道正在发送和接收的字节数,这可能不是您想要的协议类型。

另一种类型的协议是基于二进制的,具有在标头中发送的固定大小的消息。这样做的好处是可以确切地知道客户端预计会接收多少数据。它还可以根据您的发送内容为您节省带宽。虽然,ascii也可以节省空间,但这取决于您的应用程序要求。基于二进制协议的缺点是只需查看它就很难理解....需要您不断查看文档。

在实践中,我倾向于根据我的应用程序的要求,在我定义的协议中混合使用这两种策略。

答案 3 :(得分:0)

我强烈建议尽可能使用plain ASCII text。 它使错误更易于检测和修复。

一些常见的,机器可读的ASCII文本协议(大致按复杂程度排列):

世界已经足够复杂,所以我尝试使用最不复杂的协议。 将两个用户生成的字符串从一台机器发送到另一台机器 - netstrings是我列表中最简单的协议,因此我会选择netstrings。 (即使用户键入一些冒号或分号或双引号或制表符,网络字符串也能正常工作 - 不像其他格式会阻塞某些常用字符)。

我同意,如果存在某种方式在单个共享文件中描述协议,那么服务器和客户端都可能以某种方式“#include”或以其他方式使用该协议,那将会很好。 然后,当我修复协议中的错误时,我可以在一个地方修复它,重新编译服务器和客户端,然后事情就会工作 - 而不是在两边挖掘一堆硬连线常量。 / p>

有点像编写良好的C代码和C ++代码在头文件中使用函数原型的方式,以便在一侧调用函数的代码和另一侧的函数本身可以以一种方式传递参数双方都期待。

告诉我你是否发现了类似的东西,好吗?