正确实现多线程+套接字应用程序

时间:2011-07-10 18:34:38

标签: c# multithreading networking unity3d

我有一个服务器和一个客户端应用程序,这里是它当前实现的方式:服务器在其自己的线程中有一个循环,它通过TcpListener监听新连接。如果有人连接,它会将TcpClient传递给一个专门侦听该TcpClient的循环,并通过NetworkStream处理与该用户的所有交互。

在客户端上,我有一个连接到服务器的TcpClient。我的理解是我需要将它分支到不同的线程,因为任何IO都会将其置于阻塞模式,我不能让它停止主线程。

到目前为止,我是否理解正确?是否有更简单的方法来确保异步通信而不停止任何程序的主线程?

无论哪种方式,对于我的主要问题:我如何确保所有这些线程和套接字都被妥善处理?如果一个程序在仍然处于阻塞模式时退出,它似乎就会冻结。那么如何中止套接字上的所有IO并告诉子线程中的无限循环呢?

顺便说一句,这也是一个Unity3d项目,以防万一。

2 个答案:

答案 0 :(得分:3)

将每个新连接移交给自己的线程可能会限制您的可扩展性。此外,没有理由要求客户端中的I / O进行线程切换。

您可以使用异步I / O解决这两个问题。客户端上的BeginConnect/EndConnect,服务器端的BeginRead/EndRead, BeginWrite/EndWrite用于读取和写入。

然后一切都可以是事件驱动的,而不需要你自己的新线程。连接完成触发首先异步读取,然后每个读取完成在该套接字上发布新的异步读取调用 - 无论如何写入始终是POV的确定性。

关闭套接字会导致挂起的读/写错误退出,然后您应该能够干净地退出进程。小心你实现了适当的锁定(可能只需lock()),以确保套接字在关闭后不会在任何地方使用。

答案 1 :(得分:1)

你应该有两个独立的线程,一个用于TcpListener,另一个用于TcpClient自己运行的线程。初始化新线程时,将其IsBackground属性设置为true,这样如果应用程序终止,它也将终止。

Thread listenerThread = new Thread(ListenerLoop);
listenerThread.IsBackground = true;
listernerThread.Start();

如果您使用的是4.0或Task而非线程,则可以使用ThreadPool.QueueUserWorkItem