【发布时间】:2010-11-22 10:43:16
【问题描述】:
我的服务器/客户端启动一个新线程“readerThread()”来读取传入的 tcp 流量。该线程在 read() 上阻塞。我怎样才能退出这个 readerThread()。
一种方法是启动另一个线程,该线程在要退出线程时关闭套接字,以便退出读取。有没有更清洁/更好的方法。
【问题讨论】:
标签: c# multithreading tcp
我的服务器/客户端启动一个新线程“readerThread()”来读取传入的 tcp 流量。该线程在 read() 上阻塞。我怎样才能退出这个 readerThread()。
一种方法是启动另一个线程,该线程在要退出线程时关闭套接字,以便退出读取。有没有更清洁/更好的方法。
【问题讨论】:
标签: c# multithreading tcp
如果您使用阻塞式 read() 命令,您应该几乎总是有另一个控制线程负责关闭它并清理套接字。
不过,通常情况下,我会使用一个 select() 调用,该调用在 1 秒左右后超时来测试是否有要读取的数据,并且每个超时周期都会检查另一个线程是否设置了关闭状态标志。
但如果您使用纯阻塞,请按照您的建议使用控制线程。
【讨论】:
我会使用 Asnyncronous Socket 通信。我写了一篇文章,在我的博客上演示了这一点。你可以在这里阅读:
安德鲁
【讨论】:
另一种方法是当你想关闭它时,从你自己的应用程序的其他地方向你的监听套接字发送一个 0 字节的数据包。
我发现这比从另一个线程关闭 coket 稍微干净一些,因为如果关闭其上的套接字,侦听线程将引发异常。
【讨论】:
我有点困惑你到底在做什么:.NET 中的 Socket 类没有 read() 方法。
我的建议是创建第二个套接字,它正在侦听特定端口,并将线程块放在Socket.Select 中。连接到第二个套接字应该被视为关闭请求(可能在适当的身份验证之后,例如通过该套接字发送应用程序密码)。
【讨论】:
我误解了这个问题。这是我认为你应该做的。
如果你在父线程中创建了套接字,并且只使用新线程来读取传入的数据,那么我建议调用 Socket.Shutdown()。这样 Receive 方法将返回 0(不读取字节),您可以退出线程的方法。关闭将禁用发送/接收,但如果缓冲区中有任何数据等待发送/接收,它将确保在关闭套接字之前发送/接收它。如果您在接收时阻塞套接字时调用关闭,则接收方法将返回 0,但它会抛出套接字异常,套接字错误代码 = Shutdown(或 10058)。所以准备好抓住它并处理它。
如果您在新线程中创建套接字,并且它接受新连接(Socket.Listen() 和 Socket.Accept),那么您可以从父线程连接到该套接字并发送 0 个字节。当 Receive 方法返回 0 字节时,您可以退出新线程。
如果您在新线程中创建套接字,并且它只能是一个客户端(与其他套接字连接),那么这根本不是一个好方法。您可能必须中止线程(不推荐),除非您将服务器配置为在您希望客户端套接字关闭时发送 0 字节,但这样您的客户端应用程序将依赖服务器来关闭套接字。
【讨论】: