0

In my socket-application I want about 80-100 clients to be connected to my server simultaneously.

Here the socket.BeginAccept part of my server:

try
{
    _serverSocket.Bind(localEndPoint);
    _serverSocket.Listen(100);

    while (maintainActiveSocket)
    {
        _serverSocket.BeginAccept(new AsyncCallback(Accept), _serverSocket);
        clientAccepted.WaitOne();
    }
}

So as soon as one of my clients tries to connect to the server this is called, it checks if this client is already known and if not adds him to a ConcurrentDictionary, after it starts socket.BeginReceive to constantly try to receive in a while-loop for as long as this socket is connected. This while-loop throws a NullReferenceException the second time it receives data. The acceptedClient.sCom.Buffer should be byte[2048] but the second time it receives data it is null. Why is this and how can I fix it?

Socket socket = _serverSocket.EndAccept(ar);
clientAccepted.Set();
_Client acceptedClient = new _Client();

if (!Dict.connectedClients.Any((a) => a.Value.Socket == socket))
{
    acceptedClient.Socket = socket;
    Dict.connectedClients.TryAdd(getFirstKey(), acceptedClient);
}

acceptedClient = Dict.connectedClients.Single((a) => a.Value.Socket == socket).Value;

while (socket.Connected)
{
    socket.BeginReceive(
        acceptedClient.sCom.Buffer, 0, acceptedClient.sCom.Buffer.Length, 0, 
        new AsyncCallback(Receive), acceptedClient);

    receiveDone.WaitOne();
}

As soon as the socket starts receiving this is finally called:

private static void Receive(IAsyncResult ar)
{
    _Client client = (_Client)ar.AsyncState;
    Logger.Instance.Log("Receiving on " + client.Socket.Handle);
    int bytesRead = client.Socket.EndReceive(ar);

    Logger.Instance.Log("received " + bytesRead.ToString());

    for (int i = 0; i < bytesRead; i++)
    {
        client.sCom.TransmissionBuffer.Add(client.sCom.Buffer[i]);
        client.sCom = client.sCom.DeSerialize();
        Logger.Instance.Log("name: " + client.Clientname);
        receiveDone.Set();
    }
}

The received data is previously buffered in sCom.Buffer which is a byte[2048]. It is then copied to sCom.TransmissionBuffer which is a List and is deserialized afterwards.

I don't understand why the Buffer in my second code-block is null after working fine for the first iteration of the loop.

dertkw
  • 7,798
  • 5
  • 37
  • 45
octavio
  • 456
  • 4
  • 14
  • 1
    possible duplicate of [What is a NullReferenceException and how do I fix it?](http://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – BartoszKP Jun 21 '14 at 09:15
  • You are assuming that you'll received an entire "message" so that DeSerialize can work correctly. This is not guaranteed with TCP. You must be able to receive bytes one at a time. – usr Jun 21 '14 at 09:16

1 Answers1

1

Your question did not include any information about the _Client class, which I presume is not a standard library class. So this is merely a stab in the dark:

I am not sure what the line client.sCom = client.sCom.DeSerialize(); does, but it seems to replace the sCom object with a new one. The old sCom object clearly had a buffer!=null, otherwise the line before that one would have caused a crash. Presumably the new sCom object does not have an initialized buffer.


This is not directly related, but I have to comment on your use of ConcurrentDictionary:

if (!Dict.connectedClients.Any((a) => a.Value.Socket == socket))
{
    acceptedClient.Socket = socket;
    Dict.connectedClients.TryAdd(getFirstKey(), acceptedClient);
}

acceptedClient = Dict.connectedClients.Single((a) => a.Value.Socket == socket).Value;

Dict.connectedClients.Any(...) will enumerate the entire content of the dictionary, until it finds a matching value. It is not threadsafe and it will not use the fast lookup that makes a dictionary useful, so in essence you are simply using a list.

Dict.connectedClients.Single(...); has the same problems.

Community
  • 1
  • 1
HugoRune
  • 13,157
  • 7
  • 69
  • 144