开发者

Approaches to programming application-level protocols?

开发者 https://www.devze.com 2023-02-27 10:19 出处:网络
I\'m doing some simple socket programming in C#. I am attempting to authenticate a user by reading the username and password from the client console, sending the credentials to the server, and returni

I'm doing some simple socket programming in C#. I am attempting to authenticate a user by reading the username and password from the client console, sending the credentials to the server, and returning the authentication status from the server. Basic stuff. My question is, how do I ensure that the data is in a format that both the server and client expect?

For example, here's how I read the user credentials on the client:

          开发者_如何学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();

Here I am delimiting the username and password with a colon (or some other symbol) on the client side. On the server I simply split the string using ":" as the token. This works, but it seems sort of... unsafe. Shouldn't there be some sort of delimiter token that is shared between client and server so I don't have to just hard-code it in like this?

It's a similar matter for the server response. If the authentication is successful, how do I send a response back in a format that the client expects? Would I simply send a "SUCCESS" or "AuthSuccessful=True/False" string? How would I ensure the client knows what format the server sends data in (other than just hard-coding it into the client)?

I guess what I am asking is how to design and implement an application-level protocol. I realize it is sort of unique to your application, but what is the typical approach that programmers generally use? Furthermore, how do you keep the format consistent? I would really appreciate some links to articles on this matter as well.


Rather than reinvent the wheel. Why not code up an XML schema and send and receive XML "files".

Your messages will certainly be longer, but with gigabyte Ethernet and ADSL this hardly matters these days. What you do get is a protocol where all the issues of character sets, complex data structures have already been solved, plus, an embarrassing choice of tools and libraries to support and ease your development.


I highly recommend using plain ASCII text if at all possible. It makes bugs much easier to detect and fix.

Some common, machine-readable ASCII text protocols (roughly in order of complexity):

  • netstring
  • Tab Delimited Tables
  • Comma Separated Values (CSV) (strings that include both commas and double-quotes are a little awkward to handle correctly)
  • INI file format
  • property list format
  • JSON
  • YAML Ain't Markup Language
  • XML

The world is already complicated enough, so I try to use the least-complex protocol that would work. Sending two user-generated strings from one machine to another -- netstrings is the simplest protocol on my list that would work for that, so I would pick netstrings. (netstrings will will work fine even if the user types in a few colons or semi-colons or double-quotes or tabs -- unlike other formats that choke on certain commonly-typed characters).

I agree that it would be nice if there existed some way to describe a protocol in a single shared file such that that both the server and the client could somehow "#include" or otherwise use that protocol. Then when I fix a bug in the protocol, I could fix it in one place, recompile both the server and the client, and then things would Just Work -- rather than digging through a bunch of hard-wired constants on both sides.

Kind of like the way well-written C code and C++ code uses function prototypes in header files so that the code that calls the function on one side, and the function itself on the other side, can pass parameters in a way that both sides expect.

Tell me if you discover anything like that, OK?


Basically, you're looking for a standard. "The great thing about standards is that there are so many to choose from". Pick one and go with it, it's a lot easier than rolling your own. For this particular situation, look into Apache "basic" authentication, which joins the username and password and base64-encodes it, as one possibility.


I have worked with two main approaches.

First is ascii based protocol.

Ascii based protocol is usally based on a set of text commands that terminate on some defined delimiter (like a carriage return or semicolon or xml or json). If your protocol is a command based protocol where there is not a lot of data being transferred back and forth then this is the best way to go.

FIND\r
DO_SOMETHING\r

It has the advantage of being easy to read and understand because it is text based. The disadvantage (may not be a problem but can be) is that there can be an unknown number of bytes being transferred back and forth from the client and the server. So if you need to know exactly how many bytes are being sent and received this may not be the type of protocol you want.

The other type of protocol is binary based with fixed sized messages that are sent in the header. This has the advantage of knowing exactly how much data the client is expected to receive. It also can potentially save you bandwith depending on what your sending across. Although, ascii can also save you space too, it depends on your application requirements. The disadvantage of a binary based protocol is that it is difficult to understand by just looking at it....requiring you to constantly look at documentation.

In practice, I tend to mix both strategies in protocols I have defined based on my application's requirements.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号