C# 程序挂在 Socket.Accept() 上

Sea*_*ean 1 c# sockets multithreading

我创建了一个使用套接字和多线程技术的服务器“中间人”应用程序(ServerListener 在新线程中运行)。我很早就发现,当我使用 Socket.Accept() 方法时,程序会无限期挂起,等待连接发生。问题是,据我所知,没有理由不这样做。

我花了一天的大部分时间尝试很多不同的事情来让它发挥作用,但某些地方发生了变化,因为它突然开始工作了一段时间。然而,一旦我不小心为客户端应用程序选择了与“localhost”不同的数据源,问题就会再次出现。我尝试在没有运行防火墙或防病毒软件的情况下运行该程序,但没有成功。客户端程序设置为连接端口 10000。这是我的代码:

    public void ServerListener() {
        UpdateStatus("Establishing link to server");
        server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        server.Bind(new IPEndPoint(IPAddress.Any, defaultPort));
        server.Listen(queue);
        UpdateStatus("Accepting Connections");
        while (true) {
            Socket client = default(Socket);
            try {
                client = server.Accept();
                if (client != null) {
                    ++count;
                    UpdateCount(count.ToString());
                    new Thread(
                    () => {
                        Client myclient = new Client(client, defaultPort, this);
                    }
                    ).Start();
                }
            }
            catch( Exception ex ){
                MessageBox.Show(ex.ToString());
                client.Close();
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

它将正常运行,直到 server.Accept(),然后挂起。如前所述,它之前确实工作了一段时间,但现在又挂了。我尝试查看是否有其他程序正在使用端口 10000,但没有。我和朋友仔细检查了一遍,也没找到问题所在。请帮忙!

编辑要明确的是,我确实知道 Accept 是一个阻塞调用。客户端程序在端口 10000 上建立连接,但该程序继续等待 Accept,就像什么都没发生一样。它确实工作了一段时间,所以我知道连接正在像客户端程序端预期的那样工作。但是,我无法理解为什么这个程序现在表现得好像连接从未发生过,并继续等待接受。

Nik*_*off 5

Accept故意阻止。如果您想在等待另一个客户端连接时执行其他操作,您可以:

  1. ServerListener在另一个线程或更好的线程中运行- 一个长时间运行的任务:

    using System.Threading.Tasks;
    ...
    Task.Factory.StartNew(ServerListener, TaskCreationOptions.LongRunning);
    
    Run Code Online (Sandbox Code Playgroud)
  2. 使用使用类的AcceptAsync方法。为此,您需要创建一个新实例,设置其值并将其传递给.SocketAsyncEventArgsSocketAsyncEventArgssocket.AcceptAsync

  • @Gusdor `TaskCreationOptions.LongRunning` 向 TaskFactory 发出信号,表明您将给我的该线程不太可能很快返回。这意味着任务工厂不是从线程池中获取线程,而是创建一个新线程。 (2认同)