C# 正确实现多线程+;套接字应用程序
我有一个服务器和一个客户端应用程序,下面是它当前的实现方式:服务器在自己的线程中有一个循环,它通过TcpListener侦听新的连接。如果有人连接,它会将TcpClient传递给一个专门侦听该TcpClient的循环,并通过NetworkStream处理与该用户的所有交互 在客户机上,我有一个连接到服务器的TcpClient。我的理解是,我需要将它分支到另一个线程,因为任何IO都会将它置于阻塞模式,我不能让它停止主线程 到目前为止,我的理解正确吗?有没有更简单的方法可以在不停止两个程序的主线程的情况下测量异步通信 不管怎样,对于我的主要问题:如何确保所有这些线程和套接字都被正确地处理?如果程序在阻塞模式下退出,它似乎会冻结。那么,我如何中止套接字上的所有IO并告诉子线程中的无限循环我们已经完成了C# 正确实现多线程+;套接字应用程序,c#,multithreading,networking,unity3d,C#,Multithreading,Networking,Unity3d,我有一个服务器和一个客户端应用程序,下面是它当前的实现方式:服务器在自己的线程中有一个循环,它通过TcpListener侦听新的连接。如果有人连接,它会将TcpClient传递给一个专门侦听该TcpClient的循环,并通过NetworkStream处理与该用户的所有交互 在客户机上,我有一个连接到服务器的TcpClient。我的理解是,我需要将它分支到另一个线程,因为任何IO都会将它置于阻塞模式,我不能让它停止主线程 到目前为止,我的理解正确吗?有没有更简单的方法可以在不停止两个程序的主线程的
顺便说一下,这也是一个Unity3d项目,以防发生任何变化。您应该有两个单独的线程,一个用于
TcpListener
,另一个用于运行在那里的TcpClient
。初始化新线程时,将其属性设置为true,这样,如果应用程序终止,它也将终止
Thread listenerThread = new Thread(ListenerLoop);
listenerThread.IsBackground = true;
listernerThread.Start();
如果使用4.0或
线程池,则可以使用Task
。QueueUserWorkItem
而不是线程。您应该有两个单独的线程,一个用于TcpListener
,另一个用于自己运行的TcpClient
。初始化新线程时,将其属性设置为true,这样,如果应用程序终止,它也将终止
Thread listenerThread = new Thread(ListenerLoop);
listenerThread.IsBackground = true;
listernerThread.Start();
如果使用4.0或线程池,则可以使用
Task
。QueueUserWorkItem而不是线程。将每个新连接转移到自己的线程可能会限制您的可扩展性。此外,没有理由要求客户端中的I/O线程切换
您可以通过在客户端使用异步I/O来解决这两个问题。BeginConnect/EndConnect
,在服务器端使用BeginRead/EndRead、BeginWrite/EndWrite
进行读写
然后,一切都可以是事件驱动的,而不需要您自己的新线程。Connect completion首先触发异步读取,然后每次读取完成都会在该套接字上发布一个新的异步读取调用—无论如何,从POV来看,写入总是确定的
关闭套接字将导致挂起的读/写错误退出,然后您应该能够干净地退出进程。请小心实施适当的锁定(您可能只需要
lock()
),以确保套接字关闭后不会在任何地方使用。将每个新连接转移到自己的线程可能会限制您的可扩展性。此外,没有理由要求客户端中的I/O线程切换
您可以通过在客户端使用异步I/O来解决这两个问题。BeginConnect/EndConnect
,在服务器端使用BeginRead/EndRead、BeginWrite/EndWrite
进行读写
然后,一切都可以是事件驱动的,而不需要您自己的新线程。Connect completion首先触发异步读取,然后每次读取完成都会在该套接字上发布一个新的异步读取调用—无论如何,从POV来看,写入总是确定的
关闭套接字将导致挂起的读/写错误退出,然后您应该能够干净地退出进程。请小心实施适当的锁定(您可能只需要
lock()
),以确保套接字关闭后不会在任何地方使用。您给了我很多研究机会!谢谢,我想我可能做了一些非常不切实际的事情。你给了我很多研究的机会!谢谢,我想我可能做了一些非常不切实际的事情。你不是说N+1线程吗?一个用于侦听器,一个用于每个客户端?@EJP:是的,一个用于每个tcpClient。你不是说N+1个线程吗?一个用于侦听器,一个用于每个客户端?@EJP:是的,一个用于每个tcpClient。