Okay, so I've got a TCP Asynchronous Multithreaded server running which interacts with multiple clients at the same time.

It works fine unless a client sends many messages in a short peroid of time, for example five messages within about half a second. For some reason it only recieves the first four of these and ignores the fifth. I've debugged the application and it seems it doesn't even see a packet coming in when it ignores them, but I know it's being sent by the client because I've packet logged it via WPE Pro.

My code for receiving is:

private void Run()
        {
            try
            {
                if (ClientCallback != null && ClientSocket.Connected)
                {
                    Output.Write("Server", false, "Receiving packet...");
                    ClientSocket.BeginReceive(Buffer, 0, Buffer.Length, SocketFlags.None, ClientCallback, null);
                }
                else
                {
                    Disconnect(1000);
                }
            }
            catch (Exception e)
            {
                Output.Write("Client " + ClientID, true, e.ToString());
                Disconnect(1000);
            }
        }

And the code for finishing the receive is:

private void Receive(IAsyncResult result)
        {
            try
            {
                Output.Write("Server", false, "Received packet.");

                // Finish receiving the data
                int PacketLength = ClientSocket.EndReceive(result);
                RecvPacket.SetPacket(System.Text.Encoding.Default.GetString(Buffer, 0, PacketLength));

                Output.Write("Server", false, "Packet: " + RecvPacket.GetPacket());

                // Check packet length
                if (RecvPacket.GetLength() <= 0)
                {
                    // Client disconnected
                    Disconnect(1000);
                }
                else
                {
                    // Parse the packet
                    PacketParser.ParsePacket(RecvPacket);

                    // Continue running
                    Run();
                }
            }
            catch (Exception e)
            {
                if (!(e is System.Net.Sockets.SocketException))
                {
                    Output.Write("Client " + ClientID, true, e.ToString());
                }

                Disconnect(1000);
            }
        }

This all works fine as I said if the client is sending only about one or two messages per second, but sending a lot of messages works only about 90% of the time. Since I know these messages are being sent I'm very confused on how to fix this problem.

Any ideas?

Recommended Answers

All 4 Replies

Your problem probably comes from line 25 where you are attaching another reader to the socket each time you receive a message. You should have the reading in a loop or disconnect the current reader from the socket before you call Run() again.

This should fix your problem:

private void Receive(IAsyncResult result) {
    while (true) {
        try {
            Output.Write("Server", false, "Received packet.");
        
            // Finish receiving the data
            int PacketLength = ClientSocket.EndReceive(result);
            RecvPacket.SetPacket(System.Text.Encoding.Default.GetString(Buffer, 0, PacketLength));
       
            Output.Write("Server", false, "Packet: " + RecvPacket.GetPacket());
       
            // Check packet length
            if (RecvPacket.GetLength() <= 0) {
                // Client disconnected
                break;
            } else {
                // Parse the packet
                PacketParser.ParsePacket(RecvPacket);
            }
        } catch (Exception e) {
            if (!(e is System.Net.Sockets.SocketException)) {
                Output.Write("Client " + ClientID, true, e.ToString());
            }
            break;
        }
    }

    Disconnect(1000);
}

Doesn't appear to work - I get the Socket Exception:

Exception:Thrown: "EndReceive can only be called once for each asynchronous operation." (System.InvalidOperationException)
A System.InvalidOperationException was thrown: "EndReceive can only be called once for each asynchronous operation."

When the server attempts to receive the second packet (out of several).

BeginReceive must be called before EndReceieve so I don't see how I could have the EndReceive function in a loop..

Okay sorry for the double post but I've found the issue, but I'm not entirely sure how to solve it:

The server does receive all the packets, but if they're sent too closely it groups them together. For example, instead of:

Receive - This is Packet 1
Receive - This is Packet 2
Receive - This is Packet 3

The server will receive:

Receive - This is Packet1This is packet 2This is packet3

Due to this it will only parse Packet 1 (it checks the packet header of the received data then parse it based on that), so I'm not sure how to solve this really? In case it's relevant, parse packet goes like this:

public void ParsePacket(Packet RecvPacket)
        {
            String Header = RecvPacket.GetString(2);

            switch (Header)
            {
                case "\x01\x00":
                    // Do whatever
                    break;

                case "\x02\x00":
                    // Do whatever 2
                    break;
            }
}

And so on... Maybe a check in that could work but it might be a bit cpu hefty?

Solved, simply checked whether the packet was longer than it should have been (each packet from the client specifies the length it should have):

if (RecvPacket.GetLength() > Length)
            {
                //Output.Write("Client " + ClientID, false, "Multiple packets combined, parsing the packet again");
                ReParse(RecvPacket.GetPacket().Substring(Length));
            }
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.