66020

C# best way to differentiate socket messages

Question:

Im new to sockets, and Im creating a tictactoe online, I know how to make the connections with the clients and the server, but I will make a chat too.

Then I doing this, when a user chat I send a message with a prefix "CHAT: HELLO WORLD" and when a user make a move I send a message without the prefix... this is the best way?

THX!!!

Answer1:

In defining a wire protocol over a stream-based protocol like TCP, you have a few options for constructing messages:

<ul><li><strong>Fixed-length</strong> <ul><li>All messages are the same length; every sequence of x bytes represents a new message.</li> </ul></li> <li><strong>Length-prefixed</strong> (variable length) <ul><li>The first byte(s) of the message represent the length of the payload to follow.</li> </ul></li> <li><strong>String-terminated</strong> (variable length) <ul><li>Read bytes from the stream until you come to a specified byte-string that represents the end of a message, i.e. the newline character \n.</li> </ul></li> </ul>

If you ever intend on changing the protocol (protip: you will, even if you don't think you will), it is crucial that you include an identifier for the protocol version in each message to prevent issues when dealing with clients using an older iteration of the protocol. Clearly, this is the first thing you must determine before deciphering the rest of the payload, so this should be the first byte(s) of the message (following any length-prefix) - how could we determine the version if we don't know where it is located in <em>every</em> message we receive?

Answer2:

Typically you would go with a format that includes a packet length, type and payload.

In your case you could go with a Byte (type), Int16 (length), Byte[] (payload).

The type can be represented in code as an enum. Length would just represent the length of the payload.

public enum Byte PacketType { PlayerMove = 1, PlayerChat = 2 }

Answer3:

<em>You</em> need to define a protocol. Remember to allow room for additional features :-).

Eg. using regular expressions over complete lines (end with selected line terminator):

<ul><li>Matching ^:[a-c][1-3]:: is a move (colon, position, colon user name).</li> <li>Matching ^!.*?:: is a chat message (exclamation point, name, colon, text).</li> </ul>

and anything else (in V1) is an error.

Remember:

<ul><li>Data is sent in packets, you might need multiple reads from the socket to get a complete message.</li> <li>Avoid ambiguity: resolving it might be x or y is hard.</li> <li>Specify a text encoding (eg. UTF-8).</li> </ul>

Answer4:

I assume you're using TCP?

You need to make sure you 'frame' both messages so you can identify them and also avoid potential blocking issues (in case the client stops sending while you are still expecting to read CHAT: or whatever you define). With TCP your byte order is guaranteed but reading does not guarantee a complete 'packet' so you'll need to implement some way of building up a buffer and identifying when your 'message' is complete.

A reasonably simple way of doing this is to make sure each 'message' has a header with the type and size specified.

EG:

Enumerate your message types (move and chat currently), so say 'chat' is 0x01 and your message is 1020 bytes. You can prefix your 'message' with 0x0103FC so the server knows how many bytes to expect, and build up a buffer using async socket calls until the 1020 bytes are read (or you arbitrarily decide that the client is not sending anymore)

Recommend

  • Script to generate N number of valid ip addresses?
  • CSS method instead of display:run-in; to position a block inline?
  • What is the possible benefit (if any) of allowing recursive constructors?
  • ANTLR generating empty conditions
  • python subprocess.stdout.readline doesn't
  • My PHP newline beginner code isn't going to a new line. Little help?
  • How can I overwrite a file in UWP?
  • How can I prevent duplicate wrappers on a jQuery DataTable when navigating back in the presence of T
  • Quoted parameter expansion with quoted modifier in Bash
  • Creating A C# & XNA 'Monster Dash' Like Game
  • What is the ClojureScript analogue of delete from JavaScript?
  • JSeperator in JToolBar moves the components to right end
  • How does one get div content line-by-line with Javascript?
  • Standard way for writing a debug mode in C++
  • Complex python3 csv scraper
  • How do I read and write repeatedly from a process in vim?
  • Why does this empty dict break shared references?
  • Whats the right place for testhelper-classes? (phpunit/best practise)
  • Making Cross Site Asynchronous HTTP Post from GWT Client
  • Using HTML/CSS for UI in XNA?
  • Receiver has no segue with identifier“***”
  • C function strchr - How to calculate the position of the character?
  • Primefaces lazy datascroller calling load twice
  • How to access meteor package name inside package?
  • Rest Services conventions
  • SonarQube: Cannot deactivate rule with missing quality profile
  • Trying to get the char code of ENTER key
  • SAXReader not re-ecape characters
  • IE7 and TinyMCE with Plone
  • Unable to get column index with table.getColumn method using custom table Model
  • preg_replace Double Spaces to tab (\\t) at the beginning of a line
  • Deserializing XML into class C#
  • Why is the timeout on a windows udp receive socket always 500ms longer than set by SO_RCVTIMEO?
  • 0x202A in filename: Why?
  • How to include full .NET prerequisite for Wix Burn installer
  • Buffer size for converting unsigned long to string
  • Hits per day in Google Big Query
  • How to get Windows thread pool to call class member function?
  • costura.fody for a dll that references another dll
  • jQuery Masonry / Isotope and fluid images: Momentary overlap on window resize