0

我正在用 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

4 回答 4

1

如果可能的话,我强烈建议使用纯 ASCII 文本。它使错误更容易检测和修复。

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

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

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

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

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

于 2011-06-14T03:29:15.967 回答
1

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

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

于 2011-04-20T06:27:12.433 回答
0

我使用了两种主要方法。

首先是基于ASCII的协议。

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

FIND\r
DO_SOMETHING\r

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

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

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

于 2011-04-20T06:33:12.743 回答
0

基本上,您正在寻找一个标准。“标准的伟大之处在于有这么多可供选择”。选择一个并使用它,这比自己滚动要容易得多。对于这种特殊情况,请查看 Apache“基本”身份验证,它加入了用户名和密码并对其进行 base64 编码,作为一种可能性。

于 2011-04-20T06:22:05.237 回答