C# 异步套接字,服务器过载时丢失数据包

发布于 2024-12-14 06:38:17 字数 6932 浏览 0 评论 0原文

我使用.Net套接字编写了一个异步服务器,当该服务器过载时(接收大量数据,例如文件),服务器不会收到所有数据包。

如果增加缓冲区的长度,我会收到更多数据,但不是所有数据包。

有人能解决我的问题吗?

我的服务器代码是:

class ServerFile
{
    #region Delegate
    private delegate void Method(ConnectionInfoFile Infos, Object Content);
    #endregion
    #region Fields
    private Int32 Port;
    private Socket ServerSocket = null;
    private List<ConnectionInfoFile> Connections = new List<ConnectionInfoFile>();
    private Dictionary<Command, Method> Map = new Dictionary<Command, Method>();
    #endregion
    #region Constructor
    public ServerFile(Int32 Port)
    {
        this.Port = Port;
        this.Map[Command.Server_User_Login] = this.Login;
    }
    #endregion
    #region Methods - Login
    private void Login(ConnectionInfoFile Client, Object Content)
    {
        Client.Id = (Int32)Content;
        Console.WriteLine("[" + DateTime.Now.ToShortTimeString() + "] - " + this.GetType().Name.Insert(6, " ") + " - The client is now authentified as '" + Client.Id + "'.");
    }
    #endregion
    #region Methods - Receive
    private void ReceiveCallback(IAsyncResult Result)
    {

        ConnectionInfoFile Connection = (ConnectionInfoFile)Result.AsyncState;
        try
        {
            Int32 BytesRead = Connection.Socket.EndReceive(Result);
            if (BytesRead != 0)
            {
                Byte[] Message = (new MemoryStream(Connection.AsyncBuffer, 0, BytesRead)).ToArray();
                Connection.Append(Message);
                Packet Packet;
                while ((Packet = Connection.TryParseBuffer()) != null)
                {
                    Console.WriteLine("[" + DateTime.Now.ToShortTimeString() + "] - " + this.GetType().Name.Insert(6, " ") + " - Command received : " + Packet.Command.ToString());
                    if (Packet.Recipient == 0)
                    {
                        if (this.Map.ContainsKey(Packet.Command))
                            this.Map[Packet.Command](Connection, Packet.Content);
                    }
                    else
                    {
                        foreach (ConnectionInfoFile Item in this.Connections)
                        {
                            if (Item.Id == Packet.Recipient)
                            {
                                Byte[] Buffer = Packet.Serialize(Connection.Id, Packet.Command, Packet.Content);
                                this.Send(Item, Buffer);
                            }
                        }
                    }
                }
                Connection.Socket.BeginReceive(Connection.AsyncBuffer, 0, Connection.AsyncBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), Connection);
            }
            else
                this.CloseConnection(Connection);
        }
        catch (SocketException E)
        {
            CloseConnection(Connection);
            Console.WriteLine("[" + DateTime.Now.ToShortTimeString() + "] - " + this.GetType().Name.Insert(6, " ") + " - Receive socket exception : " + E.SocketErrorCode);
        }
        catch (Exception E)
        {
            CloseConnection(Connection);
            Console.WriteLine("[" + DateTime.Now.ToShortTimeString() + "] - " + this.GetType().Name.Insert(6, " ") + " - Receive exception : "+ E.Message);
        }
    }
    #endregion
    #region Methods - CloseConnection
    private void CloseConnection(ConnectionInfoFile Connection)
    {
        Connection.Socket.Close();
        Console.WriteLine("[" + DateTime.Now.ToShortTimeString() + "] - " + this.GetType().Name.Insert(6, " ") + " - The user " + Connection.Id + " has been disconnected !");
        lock (this.Connections)
        {
            this.Connections.Remove(Connection);
        }
    }
    #endregion
    #region Methods - Send
    protected void Send(IConnectionInfo Connection, Byte[] Buffer)
    {
        Connection.Socket.BeginSend(Buffer, 0, Buffer.Length, 0, new AsyncCallback(SendCallback), Connection);
    }
    private static void SendCallback(IAsyncResult Result)
    {
        try
        {
            IConnectionInfo Connection = (IConnectionInfo)Result.AsyncState;
            Int32 BytesSent = Connection.Socket.EndSend(Result);
            Console.WriteLine("[" + DateTime.Now.ToShortTimeString() + "] - " + typeof(ServerFile).Name.Insert(6, " ") + " - Sent " + BytesSent + " bytes " + Connection.Id.ToString() + ".");
        }
        catch (Exception E)
        {
            Console.WriteLine("[" + DateTime.Now.ToShortTimeString() + "] - " + typeof(ServerFile).GetType().Name.Insert(6, " ") + " - Exception : " + E.ToString());
        }
    }
    #endregion
    #region Methods - Stop
    public void Stop()
    {
        this.ServerSocket.Close();
        this.ServerSocket = null;
    }
    #endregion
    #region Methods - Start
    public void Start()
    {
        Console.WriteLine("[" + DateTime.Now.ToShortTimeString() + "] - " + this.GetType().Name.Insert(6, " ") + " - Start listening on port " + this.Port + "...");
        this.ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        this.ServerSocket.Bind(new IPEndPoint(IPAddress.Any, this.Port));
        this.ServerSocket.Listen((Int32)SocketOptionName.MaxConnections);
        for (Int32 i = 0; i < 5; i++)
            this.ServerSocket.BeginAccept(new AsyncCallback(this.AcceptCallback), this.ServerSocket);
    }
    #endregion
    #region Methods - Accept
    private void AcceptCallback(IAsyncResult Result)
    {
        ConnectionInfoFile Connection = new ConnectionInfoFile();
        Socket Socket = (Socket)Result.AsyncState;
        try
        {

            Connection.Socket = Socket.EndAccept(Result);
            Connection.ConnectionDate = DateTime.Now;
            Console.WriteLine("[" + DateTime.Now.ToShortTimeString() + "] - " + this.GetType().Name.Insert(6, " ") + " - A new client has been registered");
            lock (this.Connections)
            {
                this.Connections.Add(Connection);
            }
            Connection.Socket.BeginReceive(Connection.AsyncBuffer, 0, Connection.AsyncBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), Connection);
        }
        catch (SocketException E)
        {
            this.CloseConnection(Connection);
            Console.WriteLine("[" + DateTime.Now.ToShortTimeString() + "] - " + this.GetType().Name.Insert(6, " ") + " - Accept socket exception: " + E.SocketErrorCode);
        }
        catch (Exception E)
        {
            this.CloseConnection(Connection);
            Console.WriteLine("[" + DateTime.Now.ToShortTimeString() + "] - " + this.GetType().Name.Insert(6, " ") + " - Accept exception: " + E.Message);
        }
        Socket.BeginAccept(new AsyncCallback(AcceptCallback), Result.AsyncState);
    }
    #endregion
}

抱歉我的英语,非常感谢。

新克里普特

I have written an asynchronous server using .Net socket, and when this server is overloaded (receiving a lot of data, file for example), all the packets are not received by the server.

If I increase the length of buffer, I receive more data but not all the packets.

Is anybody have a solution to my problem?

The code of my server is :

class ServerFile
{
    #region Delegate
    private delegate void Method(ConnectionInfoFile Infos, Object Content);
    #endregion
    #region Fields
    private Int32 Port;
    private Socket ServerSocket = null;
    private List<ConnectionInfoFile> Connections = new List<ConnectionInfoFile>();
    private Dictionary<Command, Method> Map = new Dictionary<Command, Method>();
    #endregion
    #region Constructor
    public ServerFile(Int32 Port)
    {
        this.Port = Port;
        this.Map[Command.Server_User_Login] = this.Login;
    }
    #endregion
    #region Methods - Login
    private void Login(ConnectionInfoFile Client, Object Content)
    {
        Client.Id = (Int32)Content;
        Console.WriteLine("[" + DateTime.Now.ToShortTimeString() + "] - " + this.GetType().Name.Insert(6, " ") + " - The client is now authentified as '" + Client.Id + "'.");
    }
    #endregion
    #region Methods - Receive
    private void ReceiveCallback(IAsyncResult Result)
    {

        ConnectionInfoFile Connection = (ConnectionInfoFile)Result.AsyncState;
        try
        {
            Int32 BytesRead = Connection.Socket.EndReceive(Result);
            if (BytesRead != 0)
            {
                Byte[] Message = (new MemoryStream(Connection.AsyncBuffer, 0, BytesRead)).ToArray();
                Connection.Append(Message);
                Packet Packet;
                while ((Packet = Connection.TryParseBuffer()) != null)
                {
                    Console.WriteLine("[" + DateTime.Now.ToShortTimeString() + "] - " + this.GetType().Name.Insert(6, " ") + " - Command received : " + Packet.Command.ToString());
                    if (Packet.Recipient == 0)
                    {
                        if (this.Map.ContainsKey(Packet.Command))
                            this.Map[Packet.Command](Connection, Packet.Content);
                    }
                    else
                    {
                        foreach (ConnectionInfoFile Item in this.Connections)
                        {
                            if (Item.Id == Packet.Recipient)
                            {
                                Byte[] Buffer = Packet.Serialize(Connection.Id, Packet.Command, Packet.Content);
                                this.Send(Item, Buffer);
                            }
                        }
                    }
                }
                Connection.Socket.BeginReceive(Connection.AsyncBuffer, 0, Connection.AsyncBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), Connection);
            }
            else
                this.CloseConnection(Connection);
        }
        catch (SocketException E)
        {
            CloseConnection(Connection);
            Console.WriteLine("[" + DateTime.Now.ToShortTimeString() + "] - " + this.GetType().Name.Insert(6, " ") + " - Receive socket exception : " + E.SocketErrorCode);
        }
        catch (Exception E)
        {
            CloseConnection(Connection);
            Console.WriteLine("[" + DateTime.Now.ToShortTimeString() + "] - " + this.GetType().Name.Insert(6, " ") + " - Receive exception : "+ E.Message);
        }
    }
    #endregion
    #region Methods - CloseConnection
    private void CloseConnection(ConnectionInfoFile Connection)
    {
        Connection.Socket.Close();
        Console.WriteLine("[" + DateTime.Now.ToShortTimeString() + "] - " + this.GetType().Name.Insert(6, " ") + " - The user " + Connection.Id + " has been disconnected !");
        lock (this.Connections)
        {
            this.Connections.Remove(Connection);
        }
    }
    #endregion
    #region Methods - Send
    protected void Send(IConnectionInfo Connection, Byte[] Buffer)
    {
        Connection.Socket.BeginSend(Buffer, 0, Buffer.Length, 0, new AsyncCallback(SendCallback), Connection);
    }
    private static void SendCallback(IAsyncResult Result)
    {
        try
        {
            IConnectionInfo Connection = (IConnectionInfo)Result.AsyncState;
            Int32 BytesSent = Connection.Socket.EndSend(Result);
            Console.WriteLine("[" + DateTime.Now.ToShortTimeString() + "] - " + typeof(ServerFile).Name.Insert(6, " ") + " - Sent " + BytesSent + " bytes " + Connection.Id.ToString() + ".");
        }
        catch (Exception E)
        {
            Console.WriteLine("[" + DateTime.Now.ToShortTimeString() + "] - " + typeof(ServerFile).GetType().Name.Insert(6, " ") + " - Exception : " + E.ToString());
        }
    }
    #endregion
    #region Methods - Stop
    public void Stop()
    {
        this.ServerSocket.Close();
        this.ServerSocket = null;
    }
    #endregion
    #region Methods - Start
    public void Start()
    {
        Console.WriteLine("[" + DateTime.Now.ToShortTimeString() + "] - " + this.GetType().Name.Insert(6, " ") + " - Start listening on port " + this.Port + "...");
        this.ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        this.ServerSocket.Bind(new IPEndPoint(IPAddress.Any, this.Port));
        this.ServerSocket.Listen((Int32)SocketOptionName.MaxConnections);
        for (Int32 i = 0; i < 5; i++)
            this.ServerSocket.BeginAccept(new AsyncCallback(this.AcceptCallback), this.ServerSocket);
    }
    #endregion
    #region Methods - Accept
    private void AcceptCallback(IAsyncResult Result)
    {
        ConnectionInfoFile Connection = new ConnectionInfoFile();
        Socket Socket = (Socket)Result.AsyncState;
        try
        {

            Connection.Socket = Socket.EndAccept(Result);
            Connection.ConnectionDate = DateTime.Now;
            Console.WriteLine("[" + DateTime.Now.ToShortTimeString() + "] - " + this.GetType().Name.Insert(6, " ") + " - A new client has been registered");
            lock (this.Connections)
            {
                this.Connections.Add(Connection);
            }
            Connection.Socket.BeginReceive(Connection.AsyncBuffer, 0, Connection.AsyncBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), Connection);
        }
        catch (SocketException E)
        {
            this.CloseConnection(Connection);
            Console.WriteLine("[" + DateTime.Now.ToShortTimeString() + "] - " + this.GetType().Name.Insert(6, " ") + " - Accept socket exception: " + E.SocketErrorCode);
        }
        catch (Exception E)
        {
            this.CloseConnection(Connection);
            Console.WriteLine("[" + DateTime.Now.ToShortTimeString() + "] - " + this.GetType().Name.Insert(6, " ") + " - Accept exception: " + E.Message);
        }
        Socket.BeginAccept(new AsyncCallback(AcceptCallback), Result.AsyncState);
    }
    #endregion
}

Sorry for my English and thanks a lot.

NeoKript

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文