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

发布于 2024-11-19 05:52:31 字数 442 浏览 2 评论 0原文

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

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

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

无论哪种方式,对于我的主要问题:如何确保所有这些线程和套接字都得到正确处理?如果程序在仍处于阻塞模式时退出,则它似乎会冻结。那么我如何中止套接字上的所有 IO 并告诉子线程中的无限循环我们已经完成了?

顺便说一句,这也是一个 Unity3d 项目,以防发生任何变化。

I have a server and a client application, here's how it's currently implemented: The server has a loop, in its own thread, that listens for new connections through a TcpListener. If someone connects, it passes the TcpClient to a loop that listens to that TcpClient specifically, and handles all interaction with that user through NetworkStream.

On the client, I have a TcpClient that connects to the server. It's my understanding that I need to branch it to a different thread, since any IO will put it in to blocking mode, and I can't let it stop the main thread.

So far, am I understanding it correctly? Is there an easier way to asure asynchronous communication without stopping the main thread for either program?

Either way, for my main question: How do I make sure all of these threads and sockets are properly disposed of? If a program exits while it's still in blocking mode, it seems to freeze. So how do I abort all IO on the socket and tell the infinite loop in the child threads that we're done?

This is also a Unity3d project by the way, in case that changes anything.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

Saygoodbye 2024-11-26 05:52:31

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

您可以使用异步 I/O 解决这两个问题。 BeginConnect/EndConnect 在客户端,BeginRead/EndRead、BeginWrite/EndWrite 在服务器端进行读写。

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

关闭套接字将导致挂起的读/写退出并出现错误,然后您应该能够干净地退出进程。请注意,您要实施适当的锁定(可能 lock() 就可以满足您的需要),以确保套接字在关闭后不会在任何地方使用。

Handing off each new connection to its own thread could limit your scalability down the line. Also there's no reason to require thread handoff for I/O in the client.

You can resolve both issues by using async I/O. BeginConnect/EndConnect on the client, BeginRead/EndRead, BeginWrite/EndWrite on the server side for reads and writes.

Then everything can be event-driven without any need for new threads of your own. Connect completion triggers first async read, then each read completion posts a new async read call on that socket - writes are always deterministic from your POV anyway.

Closing your sockets will results in pending reads/writes exiting out with an error, and then you should be able to exit the process cleanly. Be careful that you implement appropriate locking (likely lock() will be all you need) to ensure sockets are not used anywhere after they have been closed.

你如我软肋 2024-11-26 05:52:31

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

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

如果您使用 4.0 或 ThreadPool.QueueUserWorkItem 代替线程,则可以使用 Task。

You should have two separate threads, one for TcpListener and other for the TcpClient that are running on there own. When initializing a new thread make its IsBackground property to true so that if the application terminates it will terminates too.

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

You can use Task if you are using 4.0 or ThreadPool.QueueUserWorkItem instead of thread.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文