是否有可能在服务器中将插座保持在不间断的情况下数月的线程?

发布于 2025-02-11 05:42:46 字数 2494 浏览 0 评论 0原文

我有一个在服务器上运行的.NET桌面应用程序,该应用程序的功能是从指纹和面部识别设备中收听消息,以及是否授予访问权限。

有时,应用程序停止工作。尽管它仍在运行,但看来它不再响应消息。用户永远坐在设备前,没有设备完成其身份验证过程(涉及我的应用程序)。

当出现这种情况时,我需要重新启动我的应用程序,以使所有内容再次工作。

整个过程是这样的:

  1. 我的应用程序为每个设备(每个线程上的每个设备)打开一个TCPLISTENER,
  2. 我的应用程序将每个设备配置为将消息发送到特定端口。
  3. 用户在设备上介绍自己:
  4. 设备通过套接字客户端连接发送到我的应用程序
  5. 我的应用程序将USERID发送到后端以验证。
  6. 后端以True或fals的响应,
  7. 我的应用程序将信号发送到设备以授予访问权或不给予信号。
  8. 设备向用户
  9. 设备显示一条消息,如果简单地授予访问权限,则可以打开门

,而代码看起来像:

static void Main()
{
  var devices = databaseContext.Devices;
  foreach (var device in devices)
  {
    var server = DeviceServerFactory.GetInstance(device);
    server.Start();
  }
}

class FingerPrintDeviceServer : IDeviceServer
{
  private TcpListener _listener;
  private Thread _thread;
  private bool _running = false;

  public FingerPrintDeviceServer()
  {
    _thread = new Thread(Run);
    _thread.IsBackground = True;
  }

  private async void Run()
  {
    try
    {
      _listener = new TcpListener(IPAddress.Parse(serverAddr), port);
      _listener.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
      _listener.Start();

      while(_running)
      {
        await HandleClientConnection();
      }
    }
    catch(Exception e)
    {
      Logger.Error(e);
    }
    finally
    {
      _listener.Stop();
    }
  }

  private async Task HandleClientConnection()
  {
    TcpClient client = null;
    NetworkStream stream = null;

    try
    {
      client = mServer.AcceptTcpClient();
      stream = client.GetStream();

      if (stream.CanRead && stream.DataAvailable)
      {
        // Parse the socket byte message and gets the user ID.
        var userId = GetUserId(stream);
        
        // Pass the stream to this class, because this class deals with the authentication rules and uses this stream to send the signal back to the socket client
        var backend = new BackEndClass(stream);
        await backend.validate(userId);
      }
    }
    catch (Exception e)
    {
      Logger.Error(e);
    }
    finally
    {
      stream?.Dispose();
      client?.Dispose();
    }
  }

  public void Start()
  {
    _running = true;
    _thread.Start();
  }
}

此设计有任何问题吗?因为每个设备都有一个线程和侦听器。

我需要这些线程,这些听众永远工作。线程或插座是否有时间限制,还是可以运行数周,几个月而不会中断?

OS(Windows Server)是否可以在必要时杀死线程?

无论如何都将不胜感激!

注意:防火墙无法控制,但是网络管理员向我保证,他已经打开了我需要的所有端口,没有任何阻止我的应用程序(这是有意义的(随着过程仅偶尔停止)。

I have a .NET desktop application running on a server, whose function is listen to messages from fingerprint and face recognition devices, and grant access or not.

Sometimes the application stops working. Although it is still running, it appears that it is no longer responding to messages. The users sit forever in front of the device, without the device completing its authentication process (which involves my application).

When this situation arises, I need to restart my application to get everything working again.

The whole process is this:

  1. My application opens a TcpListener for each device found (each on a separate thread)
  2. My application configures each device to send messages to a specific port.
  3. User introduces himself on the device:
  4. Device sends userid through a socket client connection to my application
  5. My application sends the userid to a backend to validate.
  6. Backend responds with true or false
  7. My application sends back a signal to the device to grant access or not.
  8. Device shows a message to the user
  9. Device opens the door if access is granted

In short, the code looks like this:

static void Main()
{
  var devices = databaseContext.Devices;
  foreach (var device in devices)
  {
    var server = DeviceServerFactory.GetInstance(device);
    server.Start();
  }
}

class FingerPrintDeviceServer : IDeviceServer
{
  private TcpListener _listener;
  private Thread _thread;
  private bool _running = false;

  public FingerPrintDeviceServer()
  {
    _thread = new Thread(Run);
    _thread.IsBackground = True;
  }

  private async void Run()
  {
    try
    {
      _listener = new TcpListener(IPAddress.Parse(serverAddr), port);
      _listener.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
      _listener.Start();

      while(_running)
      {
        await HandleClientConnection();
      }
    }
    catch(Exception e)
    {
      Logger.Error(e);
    }
    finally
    {
      _listener.Stop();
    }
  }

  private async Task HandleClientConnection()
  {
    TcpClient client = null;
    NetworkStream stream = null;

    try
    {
      client = mServer.AcceptTcpClient();
      stream = client.GetStream();

      if (stream.CanRead && stream.DataAvailable)
      {
        // Parse the socket byte message and gets the user ID.
        var userId = GetUserId(stream);
        
        // Pass the stream to this class, because this class deals with the authentication rules and uses this stream to send the signal back to the socket client
        var backend = new BackEndClass(stream);
        await backend.validate(userId);
      }
    }
    catch (Exception e)
    {
      Logger.Error(e);
    }
    finally
    {
      stream?.Dispose();
      client?.Dispose();
    }
  }

  public void Start()
  {
    _running = true;
    _thread.Start();
  }
}

Does this design have any problems? Because there is a thread and a listener for each device.

I need these threads and these listeners to work forever. Does a thread or socket have a time limit to operate, or can it run for weeks, months without interruption?

Could the OS (Windows Server) kill a thread if necessary?

Any thoughs will be appreciated!

note: The firewall is out of my control, but the network administrator assured me that he has opened all the ports I needed and nothing is blocking my application (which makes sense as the process stops only sporadically).

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

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

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

如果没有你 2025-02-18 05:42:46

此设计有任何问题吗?

您的main()函数正在运行服务器线程时退出。您不应退出main(),直到您准备退出整个程序为止。因此,main()需要等到所有听众完成工作。

另外,检查stream.canreadstream.dataavailable并不是真正的必要条件。只需调用getUserid(),然后将其阻止,直到收到完整的消息,如果出现问题,就会丢下错误。

另外,每个设备是否真的每个TCP连接仅发送1个消息?这是相当低效率的,特别是如果设备经常重新连接。至少,您的服务器线程应在循环中调用getUserid(),以防客户端决定发送多个消息。如果客户端决定在第一消息之后断开连接,则在客户端而不是服务器上。

另外,每个服务器真的一次只接收1个设备连接吗?如果有可能一次处理多个设备连接的服务器,则需要为每个接受的客户端使用单独的线程,或者至少在现有服务器线程中使用异步I/O,因此您可以在平行线。

线程或套接字是否具有操作的时间限制

的时间限制

它可以运行数周,几个月而不会中断?

是的。

OS(Windows Server)可以在必要时杀死线程吗?

不在正常情况下,没有。通常,只有没有捕获未遇到的错误。

Does this design have any problem?

Your Main() function is exiting while the server threads are running. You should not exit Main() until you are ready to exit the whole program. So Main() needs to wait until all of the listeners are done with their work.

Also, checking stream.CanRead and stream.DataAvailable is not really necessary. Just call GetUserId() and let it block until the complete message is received, throwing an error if something goes wrong.

Also, does each device really send only 1 message per TCP connection? That is fairly inefficient, especially if devices reconnect often. At the very least, your server thread should call GetUserId() in a loop in case a client decides to send multiple messages. If the client decides to disconnect after the 1st message, then that is on the client, not the server.

Also, does each server really only receive 1 device connection at a time? If there is any possibility of a server handling multiple device connections at a time, then you need to use a separate thread for each accepted client, or at least use asynchronous I/O in your existing server thread, so you can handle multiple messages in parallel.

Does a thread or socket have a time limit to operate

No.

can it run for weeks, months without interruption?

Yes.

Could the OS (Windows Server) kill a thread if necessary?

Not under normal conditions, no. Typically only if an unhandled error is not caught.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文