none
Getting SocketException while calling BeginSend RRS feed

  • Question

  • I need to write an app that accepts incoming sockect connections and sends some data to all off them every N ms.
    My code:

    private readonly Timer _senderTimer; private readonly Socket _serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

    private readonly ConcurrentDictionary<EndPoint, Socket> _clientConnections =
                new ConcurrentDictionary<EndPoint, Socket>();

    public Start(SettingsProvider settingsProvider) { _senderTimer = new Timer(SendIntervalTick, null, settingsProvider.SendInterval, Timeout.Infinite); _serverSocket.Bind(new IPEndPoint(selfIp, selfPort)); _serverSocket.Listen(MaxLengthOfPendingConnectionsQueue); _serverSocket.BeginAccept(AcceptCallback, null); } private void AcceptCallback(IAsyncResult result) { EndPoint endPoint = null; try { var acceptedSocket = _serverSocket.EndAccept(result); endPoint = acceptedSocket.RemoteEndPoint; _clientConnections.TryAdd(endPoint, acceptedSocket); } catch (Exception e) { CloseSocket(endPoint); } finally { _serverSocket.BeginAccept(AcceptCallback, null); } } private void SendIntervalTick(object state) { SendPacket(new[] {(byte)0xFF}); _senderTimer.Change(Math.Max(0, _sendInterval - watch.ElapsedMilliseconds), Timeout.Infinite); } private void SendPacket(byte[] packet) { var connToRemove = new List<EndPoint>(); var connToSend = _clientConnections.ToDictionary(x => x.Key, x => x.Value); // Send packet to all connected clients foreach (var connection in connToSend) { try { connection.Value.BeginSend(packet, 0, packet.Length, SocketFlags.None, SendCallback, new ClientConnection(connection.Key, connection.Value)); } catch (Exception e) { // Get System.Net.Sockets.SocketException (0x80004005): An established connection was aborted by the software in your host machine here!!! connToRemove.Add(connection.Key); } } // Close broken connections foreach (var endPoint in connToRemove) { CloseSocket(endPoint); } } private void SendCallback(IAsyncResult result) { var connection = (ClientConnection)result.AsyncState; try { connection.Sock.EndSend(result); } catch (Exception e) { CloseSocket(connection.RemoteEndPoint); } }

     private void CloseSocket(EndPoint endPoint)
        {
        Socket socketToClose;
        _clientConnections.TryGetValue(endPoint, out socketToClose)
        try
        {
        socketToClose.Close();
        socketToClose.Dispose();
        }
        catch (Exception e)
        {
        Logger.Error("Error of closing/disposing socket.", e);
        }
        finally
        {
        Socket removable;
        if (!_clientConnections.TryRemove(endPoint, out removable))
        {
        Logger.Warn("Can not remove an endPoint ({0}) from the client-connections-dict ({1}).",
        endPoint, string.Join(", ", _clientConnections.Keys));
        }
        }
        }

    Now I get an exception

    System.Net.Sockets.SocketException (0x80004005): An established connection was aborted by the software in your host machine

    when call BeginSend among 20-50 successful sent. What I've noticed is that exception always throws soon after new connection accepted:

    TRACE 674 bytes successfully sent to client 212.193.xxx.xxx:21666
        TRACE 674 bytes successfully sent to client 212.193.xxx.xxx:21666
        DEBUG An endPoint (212.193.xxx.xxx:22014) successfully added to the client-connections-dict (212.193.xxx.xxx:21666, 212.193.xxx.xxx:22014) 
        TRACE 674 bytes successfully sent to client 212.193.xxx.xxx:21666 
        TRACE 674 bytes successfully sent to client 212.193.xxx.xxx:22014 
        WARN Closing socket 212.193.xxx.xxx:21666 because of exception while BeginSend: System.Net.Sockets.SocketException (0x80004005): An established connection was aborted by the software in your host machine
    But I don't know why the error occurs and how to fix it. Please help!

    PS Please don't suggest to switch Firawall off, I've tried that.


    • Edited by Zharro Thursday, January 22, 2015 3:23 PM
    Thursday, January 22, 2015 2:56 PM

Answers

  • I think the code is trying to open a connection that is already opened. Since the code is working a lot of times I believe there is issues with closing one of the connections.  The server should never close a connection.  You should always have the client both open and close a socket.  TCP has a known race condition when both the client and server simultaneously attempt to close a socket.  Often the socket is left in a half open have close state.  Try eliminating the close sockets statements.


    jdweng

    Friday, January 23, 2015 11:14 AM
  • The reset flag is being sent because the client closed the socket.  When the server tried to close the same connection the reset flag occurred.  I said you can cause race conditions if both the client and server tries to simultaneously close the same connection. 

    jdweng

    Friday, January 23, 2015 3:42 PM

All replies

  • Hi,

    For this scenario, according to the error message, it seems to be related to the Windows environment, may be the third party component or software abort the connection. So, you could try another machine to have a test.

    Friday, January 23, 2015 7:18 AM
  • I think the code is trying to open a connection that is already opened. Since the code is working a lot of times I believe there is issues with closing one of the connections.  The server should never close a connection.  You should always have the client both open and close a socket.  TCP has a known race condition when both the client and server simultaneously attempt to close a socket.  Often the socket is left in a half open have close state.  Try eliminating the close sockets statements.


    jdweng

    Friday, January 23, 2015 11:14 AM
  • I've sniffed the traffic and found out that one of clients (who always was a source of problems) periodically sends tcp packet with a Reset flag. That's why I failed to send packet to it. So what would be a correct behaviour of the server in this case? Just stop sending packets to that connection?
    Friday, January 23, 2015 2:05 PM
  • The reset flag is being sent because the client closed the socket.  When the server tried to close the same connection the reset flag occurred.  I said you can cause race conditions if both the client and server tries to simultaneously close the same connection. 

    jdweng

    Friday, January 23, 2015 3:42 PM