1

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!!!

4

4 回答 4

4

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
}
于 2012-08-01T14:39:58.587 回答
4

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

  • Fixed-length
    • All messages are the same length; every sequence of x bytes represents a new message.
  • Length-prefixed (variable length)
    • The first byte(s) of the message represent the length of the payload to follow.
  • String-terminated (variable length)
    • 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.

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 every message we receive?

于 2012-08-01T15:17:58.853 回答
1

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

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

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

and anything else (in V1) is an error.

Remember:

  • Data is sent in packets, you might need multiple reads from the socket to get a complete message.
  • Avoid ambiguity: resolving it might be x or y is hard.
  • Specify a text encoding (eg. UTF-8).
于 2012-08-01T14:38:35.367 回答
0

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)

于 2012-08-01T14:40:48.353 回答