Help with Silverlight connection and message delivery
It has been 4 months since I stopped developing my Silverlight Multiplayer Chess game.
alt text http://img408.imageshack.us/img408/8355/chess.gif
The problem was a bug that I could not reproduce. I am very sad because this was a test and a lot of Silverlight multiplayer games will come if this is successful. There are no examples on the Internet of how to do this sort of thing, let alone the fact that very few people use sockets in their programming life.
Since I got some free time this week, I was able to spot the problem and now I can reproduce the bug.
It seems that if I send 10 messages from the client one by one, with no delay in between like in the example below
// when I press Enter, the client will 10 messages with no delay between them
private void textBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter && textBox.Text.Length > 0)
{
for (int i = 0; i < 10; i++)
{
MessageBuilder mb = new MessageBuilder();
mb.Writer.Write((byte)GameCommands.NewChatMessageInTable);
mb.Writer.Write(string.Format("{0}{2}: {1}", ClientVars.PlayerNickname, textBox.Text, i));
SendChatMessageEvent(mb.GetMessage());
//System.Threading.Thread.Sleep(100);
}
textBox.Text = string.Empty;
}
}
// the method used by client to send a message to server
public void SendData(Message message)
{
if (socket.Connected)
{
SocketAsyncEventArgs myMsg = new SocketAsyncEventArgs();
myMsg.RemoteEndPoint = socket.RemoteEndPoint;
byte[] buffer = message.Buffer;
myMsg.SetBuffer(buffer, 0, buffer.Length);
socket.SendAsync(myMsg);
}
else
{
string err = "Server does not respond. You are disconnected.";
socket.Close();
uiContext.Post(this.uiClient.ProcessOnErrorData, err);
}
}
// the method used by server to receive data from client
private void OnDataReceived(IAsyncResult async)
{
ClientSocketPacket client = async.AsyncState as ClientSocketPacket;
int count = 0;
try
{
if (client.Socket.Connected)
count = client.Socket.EndReceive(async);
// THE PROBLEM IS HERE
// IF SERVER WAS RECEIVE ALL MESSAGES SEPARATELY, ONE BY ONE, THE COUNT
// WAS ALWAYS 15, BUT BECAUSE THE SERVER RECEIVE 3 MESSAGES IN 1, THE COUNT
// IS SOMETIME 45
}
catch
{
HandleException(client);
}
client.MessageStream.Write(client.Buffer, 0, count);
Message message;
while (client.MessageStream.Read(out message))
{
message.Tag = client;
ThreadPool.QueueUserWorkItem(new WaitCallback(this.processingThreadEvent.ServerGotData), message);
totalReceivedBytes += message.Buffer.Length;
}
try
{
if (client.Socket.Connected)
client.Socket.BeginReceive(client.Buffer, 0, client.Buffer.Length, 0, new AsyncCallback(OnDataReceived), client);
}
catch
{
HandleException(client);
}
}
only 3 large messages are sent and each large message contains 3 or 4 small messages. This is not the behavior I want.
If I put a delay of 100 milliseconds between delivering messages, everything works fine, but in the real world, users can send messages to the server even 1 millisecond between them.
- Is there any setting so that the client can only send one message at a time, or
- Even if I get 3 messages in 1, are they constantly filling up with messages (I don't want to receive 2.5 messages in one big message)? because if they are, I can read them and consider this new situation.
a source to share
You missed the main feature of TCP - it is not a message based protocol. It sends all data through one "pipe". When you put 5 cups of water in the pipe, you get a bucket of water on the other end, not five cups. If you're quick enough to get the water out of the bucket, you can get either 5 cups, 10 cups, or one bucket. It's the same with TCP. If you want messages, you should put some markers at the beginning and end of each message and parse the stream on the receiving end.
a source to share