Question

I have a class of the logged in the clients:

public class LoggedIn_Class
{
    public Socket socket;
    public string name;
}

And I have a list:

public static List<Object> LoggedIn_List = new List<Object>();

When someone login to my server I add it to the list:

LoggedIn_Class newClient = new LoggedIn_Class();

newClient.socket = currentSocket;
newClient.name = currentName;

LoggedIn_List.Add(newClient);

Now I'm trying to send a packet to every client with this:

foreach (LoggedIn_Class s in variables.LoggedIn_List.ToArray())
{
   s.socket.Send(Packet);
}

Now the problem is the foreach processing too fast the items and it can't be send. This works properly, but I don't think this is the best solution...

foreach (LoggedIn_Class s in variables.LoggedIn_List.ToArray())
{
   s.socket.Send(Packet);
   Thread.Sleep(50);
}

Someone have any idea about this? What can I do to wait the end of the send?

Was it helpful?

Solution

I'm using TCP sockets. The client just not receive the packets, it don't have any exception.

There are plenty of answers about this. You real problem is that you have not understood what stream based protocols means. With TCP you do not send messages, you send streams of bytes.

As a result, the receiver side can not assume that everything received in one socket.Receive corresponds to exactly the same bytes as the other side sent using socket.Send.

You should therefore use some sort of mechanism to detect when a complete message have been received. Typically you either prefix each of your messages with a length prefix or use a delimiter after each message.

The reason to why it works when you use a Thread.Sleep is that the messages are short enough to be sent one at a time and you manage to receive them before the next message is sent. Without the delay, the nagle algorithm probably comes into play and merge your messages.

A naive implementation:

public void Send(byte[] msg)
{
    var header = BitConverter.GetBytes(msg.Length);
    socket.Send(header, 0, header.Length);
    socket.Send(msg, 0, msg.Length);
}

Receiver side (probably faulty, but should give you a hint):

var buffer = new byte[4];
int bytesReceived = socket.Receive(buffer, 0, 4, ....);
if (bytesReceived < 4)
{
     bytesReceived = socket.Receive(buffer, bytesReceived, 4 - bytesReceived, ....);
     //this can fail too, probably should use a loop like below until
     //all four length bytes have been received.
}

var bytesToRead = BitConverter.GetInt32(buffer, 0);
var buffer = new byte[bytesToRead];
var offset = 0;

while (bytesToRead  > 0)
{
   var len = Math.Min(bytesToRead, buffer.Length);
   var read = socket.Receive(buffer, offset, len, .....);
   bytesToRead -= read;
   offset += read;
}

//now you got everything.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top