c# - C# 中的远程主机强制关闭现有连接

标签 c# .net sockets tcp

我有基于 C# 的 Windows 服务,它使用 TCP 端口通过 Web 连接到多个客户端。服务器具有静态 IP,可帮助客户端定位服务器。我已经在这里发布了代码。

TcpListener tcp = new TcpListener(ipAddr, portNo);

tcp.Start();

listening = true;

while (listening)
{
    Socket mySocket = null;

    // Blocks until a client has connected to the server 
    try
    {
        mySocket = tcp.AcceptSocket();
        Thread.Sleep(500);

        byte[] bReceive = new byte[1024 * 1024 * 2];
        int i = mySocket.Receive(bReceive);
        byte[] databyte = new byte[i];

        for (int j = 0; j < i; j++)
        {
            databyte[j] = bReceive[j];
        }

        Analysis(databyte, mySocket);
    }
    catch (Exception exc)
    {
        logger.Error(exc);
    }
}

listening = false;
tcp.Stop();
有时我会遇到这两个错误之一,即关闭连接并且所有客户端都断开连接:
  • 远程主机在System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags).
  • 已建立的连接被主机中的软件中止System.Net.Sockets.Socket.Send(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)

  • 这些错误不是周期性的,而是会导致所有客户端在出现时断开连接。该服务连接到大约 300 个客户端。
    编辑 1:
    根据@Sean H 的建议,我修改了代码以异步读取数据。以下是代码:
    Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    
    private static Logger logger = LogManager.GetCurrentClassLogger();
    
    //constructor 
    public Server()
    {
        listener.Bind(new IPEndPoint(IPAddress.Parse("192.168.1.5"), 9000));
        listener.Listen(300);
        listener.BeginAccept(new AsyncCallback(OnConnectRequest), listener);
        //Console.Write("Server Running...\r\n");
    }
    
    public void OnConnectRequest(IAsyncResult ar)
    {
        Socket listener = (Socket)ar.AsyncState;
        Socket accepted = listener.EndAccept(ar);
        listener.BeginAccept(new AsyncCallback(OnConnectRequest), listener);
        NewConnection(accepted);
    }
    
    //send a string message over a TCP socket 
    public void sendMSG(Byte[] bSendData, ref Socket mySocket)
    {
        //some code which sends data according to my protocol
        int numBytes = 0;
    
        try
        {
            if (mySocket.Connected)
            {
                if ((numBytes = mySocket.Send(bSendData, bSendData.Length, 0)) == -1)
                {
                    logger.Error("Socket Error: Cannot Send Packet (Custom Error by me)");
                }
                else
                {
                }
            }
            else
            {
                logger.Error("Link Failed - Socket closed (Custom Error by me)");
            }
        }
        catch (Exception exc)
        {
            logger.Error(exc);
        }
    }
    
    public void receiveMSG(ref Socket mySocket)
    {
        byte[] bReceive = new byte[1024 * 1024 * 2];
        int i = mySocket.Receive(bReceive);
        byte[] databyte = new byte[i];
    
        for (int j = 0; j < i; j++)
        {
            databyte[j] = bReceive[j];
        }
    
        Analysis(databyte, mySocket);
    }
    
    
    //function called whenever a NEW CLIENT is connected
    public void NewConnection(Socket sockClient)
    {
        //Console.WriteLine("user {0} has joined", sockClient.RemoteEndPoint);
        //byte[] msg = new byte[20];
        receiveMSG(ref sockClient);
        //sockClient.Receive(msg);
    }
    
    这在测试环境中效果很好。
    我还没有将它部署在生产环境中,原因是服务器如何知道它收到的数据是否已完成,或者还有一部分字符串仍需从客户端传输到服务器。在将 Windows 服务部署到生产环境之前,我无法知道它的实际行为,因为我在测试环境中有 4 个客户端,而在生产环境中有 300 个客户端。
    但是@Sean H 的建议变得很棒,因为现在服务器不会被阻塞,直到处理来自客户端的请求。它正在同时收听多个客户。
    我对这种 TCP/IP 编程比较陌生,我的问题可能看起来很愚蠢......

    最佳答案

    我想我看到了你的问题。当您的 Analysis(byte, Socket) 方法正在运行时,您的服务器无法接受更多连接。一旦您接受来自客户端的套接字,您将不再监听该端口,直到您完成工作并再次调用 .AcceptSocket() 方法。

    相反,您应该将工作启动到异步方法,并在绑定(bind)当前客户端连接后再次开始监听。这是您想要做的一个很好的例子。

    https://docs.microsoft.com/en-us/dotnet/framework/network-programming/asynchronous-server-socket-example

    关于c# - C# 中的远程主机强制关闭现有连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46910267/

    相关文章:

    Java通过套接字发送字节[]...读取的长度错误

    c# - 何时在 windows phone 项目中实现 INotifyPropertyChanged

    c# - 以相同的顺序对两个单独的列表进行排序?

    c# - Azure 服务总线触发功能 - 绑定(bind)到 MessageReceiver

    c# - 如何激活 VsVim?

    c# - 使用 System.Runtime.Caching,但是当我去检索它时,它是空的?

    c++ - 通过一个套接字发送和接收两个结构

    c# - 如何在 VB.Net 上使用 Regex 删除字符串中的重复字符(出现次数超过 3 次)?

    asp.net - 在 .NET 6 中创建和使用类型化 http 客户端和 DI 时,我是否应该明确使用 httpClientFactory 类作为建议?

    挑战: Calculate transfer rate via UDP socket