【问题标题】:C# program hangs on Socket.Accept()C# 程序挂在 Socket.Accept() 上
【发布时间】:2014-07-15 06:16:52
【问题描述】:

我创建了一个使用套接字和多线程技术的服务器“中间人”应用程序(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();
            }
        }
    }

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

EDIT 明确地说,我知道 Accept 是一个阻塞调用。客户端程序在端口 10000 上建立连接,但该程序继续等待 Accept,就好像什么都没发生一样。它确实工作了一段时间,所以我知道连接的工作方式就像它应该从客户端程序的末端一样工作。但是,我无法理解为什么这个程序现在表现得好像连接永远不会发生,并继续等待接受。

【问题讨论】:

  • 但这就是假设的工作方式。 Accept 正在阻止呼叫。
  • 也许我应该更清楚。接受是阻塞的,但是一旦建立连接,它应该继续前进,对吗?连接是从客户端程序进来的,但是accept一直在等待,好像什么都没发生一样
  • 是的,直到下一次在您的循环中调用 Accept。听起来您在调试多线程代码时遇到了麻烦。
  • 您似乎想接受单个连接。如果是这样,为什么还要循环呢?
  • 一次可能有多个客户端连接

标签: c# multithreading sockets


【解决方案1】:

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

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

    using System.Threading.Tasks;
    ...
    Task.Factory.StartNew(ServerListener, TaskCreationOptions.LongRunning);
    
  2. 使用AcceptAsync method,后者使用SocketAsyncEventArgs class。为此,您需要创建一个新的 SocketAsyncEventArgs 实例,设置其值并将其传递给 socket.AcceptAsync

【讨论】:

  • 为什么长时间运行的任务更好?
  • 它是更高层次的抽象,当人们难以理解某个概念时,抽象特别有用。
  • ServerListener 正在另一个线程中运行。尝试使用 AcceptAsync 方法,但很难了解如何将其应用于这种情况;我的 SocketAsyncEventArgs 会有什么样的值?
  • 搞清楚了,AcceptAsync 确实很有帮助。谢谢!
  • @Gusdor TaskCreationOptions.LongRunning 向 TaskFactory 发出信号,您将给我的这个线程不太可能很快被返回。这意味着任务工厂不是从线程池中获取线程,而是创建了一个新线程。
猜你喜欢
  • 1970-01-01
  • 2019-02-16
  • 2016-07-20
  • 1970-01-01
  • 2018-01-02
  • 1970-01-01
  • 2016-07-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多