I personally thing you should design and post your protocol before attempting to build the server and client. After all the protocol is basically your entire messaging and communication backbone.
There are a few different kinds out there depending on how complex you want to make it. For example you can use a column based protocol. Example:
Code
USER Protocol
Function | Message | Channel | To-Username
TALK | "hi" | #channel | N/A
WHISPER| "hi" | N/A | "abduct"
More or less you have columns and rows depicting the arguments and function of the packet being sent, deliminated by some separator. New lines are acceptable here. For example a TALK packet might look like "TALK\nHi\n#channel" Then to parse you just break the packet on newlines and access the array of args.
Code
switch args[0]
when "TALK"
talk(args[1], args[2])
when "WHISPER"
etc
Other options are binary packets which tend to be better since you can customize the protocol more. For example you can specifcy the first byte to be the packet ID, next 2 bytes being packet length (to check for truncated/malformed packets), and then a way to extract strings, ints, etc from the packet. For example let 0x50 be "TALK", and the message and channel be strings with the implentation that the first byte is the string length. A packet my look like this:
Code
\x50\x000C\x02Hi\x08#channel
From there you will always get the first byte to determine what packet is going to be parsed, the next two bytes for packet length (sans the length identifier) so that you can discard or handle broken packets, and then parse the message for strings of X bytes in length. Since you know 0x50 is a TALK packet, and it has 2 arguments of type string, you will proceed to read the next byte (0x02) and know that the string is 2 bytes long for the message. After you read the next byte after the message (0x08) to determine you have to read 8 bytes for the channel name. What this sets up is a way for the server to handle arbitrary string lengths without having to look for identifiers such as a nullbyte or a newline as in the previous example.
Just some things to think about before going too balls deep into designing everything.
Edit:: If you need more ideas the bit torrent bencode
https://en.wikipedia.org/wiki/Bencode is another simple protocol to implement which handles strings, lists, and dictionaries.
Or I guess you can just transmit JSON strings back and form and map them to JSON mapped classes. That works too and is also advised for OOP languages.
For example in crystal you can do:
Code
class Talk
JSON.mapping({message : String, channel : String})
end
Talk.from_json("{"message" : "hi", "channel" : "#channel"}")
Talk.message
=>"hi"
Talk.channel
=>"#channel"
Where you create a class mapping, then when you parse a json string to it, it will automatically create getters so you can get the contents in an OOP way.
This post was edited by AbDuCt on Feb 13 2017 12:58pm