.NET C# 套接字并发问题

7

System.Net.Sockets.Socket的一个实例可以被两个线程共享,以便其中一个使用send()方法,另一个使用receive()方法吗?

这样做安全吗?

嗯,我需要它不仅是线程安全的,而且send/receive方法也不是同步的,以便让每个线程同时调用它们。

我有其他方法吗?

感谢您的帮助,我在Java方面有经验,但尝试做这个还是遇到了困难。

3个回答

8

是的,应该是安全的。MSDN引用中提到Socket类是完全线程安全的。

然而我不知道是否是个好主意。通过使用两个线程可能会使自己难以处理。你可能需要查看BeginSendBeginReceive来获取异步版本,在这种情况下,你不需要多个线程。


1
首先,我不仅关心线程安全,还关注读写的并发使用。嗯,好的,请允许我再问一些问题,您能回答吗?在底层,使用这些异步方法会管理另一个线程以实现异步性,对吗?如果是这样,每次调用begin...,它会创建一个新线程吗? - David Hofmann
1
据我所知,会创建一个新的线程,但并不是每次调用都会创建一个新的线程。我进行了一些测试来确认,看起来确实是这样的。 - Thorarin
2
我相信异步方法使用线程池线程,而不是创建一个特定的新线程。 - Matt
1
@Matt:没错。它可能会启动一个新线程,也可能不会,这取决于线程池中空闲线程的可用性。通常这种区别并不重要,所以我最初没有提到它。这里有一些信息:http://msdn.microsoft.com/en-us/library/ms973903.aspx - Thorarin

2

有点离题,但只有在客户端数量有限时,使用同步方法才有用。我发现异步套接字的响应速度更慢。异步套接字在处理许多客户端方面要好得多。

因此: 同步更快。 异步更具可扩展性。


1

是的,同时从两个不同的线程访问发送和接收是完全安全的。

如果您希望应用程序扩展到数百个活动套接字,则应使用BeginReceiveve/BeginSend方法,而不是手动创建线程。这将在幕后执行魔法,以便您不会生成100个线程来处理套接字。它确切地做了什么取决于平台。在Windows上,您将使用“高性能”IO完成端口。在Linux(mono)下,我认为您将使用epoll。无论哪种方式,您最终使用的线程比活动套接字少得多,这总是一件好事:)


为什么您认为使用专用线程进行接收/发送会比使用异步方法带来更大的延迟或可扩展性问题? - David Hofmann
1
假设您有500个打开的套接字,而您只需要从它们那里接收数据。你需要启动500个线程,每个线程都会在Socket.Receive()上阻塞。现在,假设您使用了异步BeginReceive方法。 .NET运行时会将套接字交给操作系统,然后说“当它们有数据时告诉我”。当它们有数据时,运行时将从线程池中获取一个线程并调用AsyncCallback,以便您可以处理数据。这比上下文切换500个线程要高效得多。 - Alan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接