This project has moved and is read-only. For the latest updates, please go here.

Index outside the bounds of the array - AcceptCompleted

Jul 28, 2010 at 8:00 AM
Edited Jul 28, 2010 at 8:05 AM

Hi there, hopefully somebody can help out.

Occassionally after a period of time of our server running we receive an exception within AcceptCompleted, but can't quite understand why and where exactly it happens, on our test server it never happens but with several hundred connections it does happen.

Our code is below, would somebody out there mind having a quite look to make sure we aren't doing anything glaringly obvious.

private void ListeningSocket_AcceptCompleted(AsyncResultEventArgs<ServerChildTcpSocket> e)
        {
            // Always continue listening for other connections
            ListeningSocket.AcceptAsync();

            // Check for errors
            if (e.Error != null)
            {
                Console.WriteLine("Error in accept completed: " + e.Error.Message);
                try
                {
                    e.Result.Close();
                }
                catch { }
                return;
            }

            

            ServerChildTcpSocket socket = e.Result;

            try
            {
                // Save the new child socket connection, and create a packetizer for it
                SocketPacketProtocol protocol = new SocketPacketProtocol(socket);
                ChildSocketContext context = new ChildSocketContext();
                context.Protocol = protocol;
                context.State = ChildSocketState.Connected;
                ChildSockets.Add(socket, context);


                protocol.PacketArrived += (args) => ChildSocket_PacketArrived(socket, args);
                socket.WriteCompleted += (args) => ChildSocket_WriteCompleted(socket, args);
                socket.ShutdownCompleted += (args) => ChildSocket_ShutdownCompleted(socket, args);

                // Start reading data from the connection
                protocol.Start();
            }
            catch (Exception ex)
            {
                Console.WriteLine("There was an error in accept completed (this is probably why its closing our connection str8 away!) " + ex.Message);
                ResetChildSocket(socket);
                //Logger.WriteEventLogEntry("ListeningSocket_AcceptCompleted", "Socket error accepting connection: [" + ex.GetType().Name + "] " + ex.Message + Environment.NewLine);
            }
        }

Error: Index was outside the bounds of the array. There was an error in accept completed An existing connection was forcibly closed by the remote host What generally happens from the client end is a user tries to connect and login and it immediately disconnects them multiple times in a row and then let's them in OK. Any ideas welcome. Thanks

Jul 28, 2010 at 2:20 PM

It looks like you have two error messages here: "Error: Index was outside the bounds of the array. There was an error in accept completed An existing connection was forcibly closed by the remote host"

Where is the "Index was outside the bounds of the array" error being thrown?

Regarding the "There was an error in accept completed: An existing connection was forcibly closed by the remote host" error:

  • Errors passed in e.Error are errors from the actual accept operation.
  • According to MSDN, this error code on an accept operation happens in this circumstance: "An incoming connection was indicated, but was subsequently terminated by the remote peer prior to accepting the call." That is, the client is connecting and then immediately aborting the connection before the server has a chance to accept it.
  • MSDN also has more information on this error code: "This normally results if the peer application on the remote host is suddenly stopped, the host is rebooted, the host or remote network interface is disabled, or the remote host uses a hard close (see setsockopt for more information on the SO_LINGER option on the remote socket)."

So, things to check would include:

  • Ensure the client program is not aborting (or being aborted) when it attempts to connect.
  • Network driver updates for the client and server machines.
  • Any updates for intermediate proxies or NATing devices.
  • Any updates for AntiVirus on the client machine.

Try to establish a profile for clients that exhibit this problem, and look for patterns.

Jul 28, 2010 at 2:39 PM
Thanks for the reply. The 'Existing connection was forcibly closed..' error is ok, we're handling that, however the 'Index outside the bounds of the array' is the one that is worrying us. We think it's being thrown on protocol.Start() We've amended the code and wrapped the "ContinueReading()" method with try/catch so we can throw the error (if one occurs). Do you have any idea why ContinueReading() would throw an index out of bounds exception? Appreciate the help
Jul 28, 2010 at 4:09 PM
Can you post the Start and ContinueReading methods?
Jul 28, 2010 at 4:14 PM
We only recently added the if ( this.bytesReceived < this.dataBuffer.Length) because we thought that might be going out of bounds
public void Start()
        {
            try
            {
                this.Socket.ReadCompleted += this.SocketReadCompleted;
                this.ContinueReading();
                
            }
            catch (Exception ex)
            {
                throw ex;
            }

        }

        /// 
        /// Requests a read directly into the correct buffer.
        /// 
        private void ContinueReading()
        {
            try
            {
                // Read into the appropriate buffer: length or data
                if (this.dataBuffer != null)
                {
                    if ( this.bytesReceived < this.dataBuffer.Length)
                    {
                        this.Socket.ReadAsync(this.dataBuffer, this.bytesReceived, this.dataBuffer.Length - this.bytesReceived);
                    }
                }
                else
                {
                    if ( this.bytesReceived < this.lengthBuffer.Length)
                    {
                        this.Socket.ReadAsync(this.lengthBuffer, this.bytesReceived, this.lengthBuffer.Length - this.bytesReceived);
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
Jul 28, 2010 at 4:43 PM

Sounds like the protocol code is incorrect.

Remove any "catch (Exception ex) { throw ex; }" statements in the code. They don't do anything except wipe out the exception call stack. Then examine the call stack for the index out of bounds error. If its not clear what's causing the problem, you'd have to post all the protocol code for me to debug it.

Jul 29, 2010 at 9:14 AM

Ah! Yes we know what the issue is now. It's a dictionary concurrency issue, we aren't actually locking the dictionary when we access it.

However this does throw up other issues, if we start locking the dictionary this is going to start blocking threads and slowing the server down.

Any alternative solutions?

Jul 29, 2010 at 1:55 PM

Well, one of the major benefits of using Nito.Async sockets is that they'll synchronize to the main thread automatically. So, ListeningSocket_AcceptCompleted should be invoked on the UI thread.

I'm not sure what the dictionary does. There is a ConcurrentDictionary in .NET 4.0 which has (mostly) lock-free access. However, you may want to restructure the logic so that the incoming messages are placed into a producer/consumer queue (along with a reference to the "source" socket). .NET 4.0 comes with a non-blocking producer/consumer queue (ConcurrentQueue) and also a blocking but mostly lock-free version (BlockingCollection).

The proper direction really depends on how you're multithreading, and I don't have a "big picture" view of your server.