调用BeginSend时获取SocketException

时间:2015-01-22 14:47:08

标签: c# sockets asynchronous asyncsocket

我需要编写一个接受传入sockect连接的应用程序,每隔 N ms将发送一些数据发送给所有人。 我的代码:

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));
        }
    }
}

现在我得到一个例外

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

当调用BeginSend时,20-50成功发送。我注意到的是,在接受新连接后,异常总是会抛出:

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

但我不知道错误发生的原因以及解决方法。请帮忙!

编辑:我已经嗅到了流量并发现其中一个客户端(总是问题来源)定期发送带有重置的tcp数据包旗。这就是我无法向其发送数据包的原因。根据{{​​3}}回答,这可能会因服务器收到的已关闭套接字数据包而发生。我想知道为什么会出现这种情况以及服务器在这种情况下应该如何表现。

0 个答案:

没有答案