简体   繁体   English

异步写入套接字线程是否安全?

[英]Are Asynchronous writes to a socket thread safe?

Consider the Socket.BeginSend() method. 考虑Socket.BeginSend()方法。 If two thread pool threads were to call this method simultaneously, would their respective messages end up mixing with each other or does the socket class keep this from happening? 如果两个线程池线程同时调用此方法,它们各自的消息是否最终会相互混合,或者套接字类是否阻止这种情况发生?

.NET Socket instances are not thread-safe in that simultaneous calls to some methods (the same or different ones) may cause inconsistent state. .NET Socket实例不是线程安全的,因为同时调用某些方法(相同或不同的方法)可能会导致状态不一致。 However, the BeginSend() and BeginReceive() methods are thread-safe with respect to themselves . 但是, BeginSend()BeginReceive()方法相对于自身是线程安全的

It is safe to have multiple outstanding calls to each (or both). 对每个(或两个)进行多次未完成的呼叫是安全的。

In the case of BeginReceive() , they will be serviced when data is available in the order called. BeginReceive()的情况下,当数据在调用的顺序中可用时,它们将被服务。 This can be useful if, for example, your processing is lengthy but you want other receives to occur as quickly as possible. 例如,如果您的处理过长但希望尽快发生其他接收,则此功能非常有用。 Of course in this case you may have your code processing multiple receipts simultaneously and you may need your own synchronization logic to protect your application state. 当然,在这种情况下,您可能会让代码同时处理多个收据,您可能需要自己的同步逻辑来保护您的应用程序状态。

In the case of BeginSend() , each call will attempt to push the sent data into the socket buffer, and as soon as it is accepted there, your callback will be called (where you will call EndSend() ). BeginSend()的情况下,每次调用都会尝试将发送的数据推送到套接字缓冲区,一旦被接受,就会调用你的回调(你将调用EndSend() )。 If there is insufficient buffer space for any call, it will block. 如果任何调用的缓冲区空间不足,它将阻塞。

Note: don't assume that the default 8k buffer means "I can quickly call BeginSend() with exactly 8k of data, then it will block," as the following are true: 注意:不要假设默认的8k缓冲区意味着“我可以用8k的数据快速调用BeginSend() ,然后它将阻塞”,如下所示:

  1. The 8K is a "nominal size" number, and the buffer may shrink and grow somewhat 8K是“标称大小”数字,缓冲区可能会缩小并有所增长

  2. As you are queing up the 8K worth of calls, data will be being sent on the network reducing that 8K of queued data 当您排队等待8K的呼叫时,将在网络上发送数据,减少8K的排队数据

In general: 一般来说:

  • If you call BeginSend() several times within a thread, you are assured that the sends will leave the machine in the order they were called. 如果在一个线程中多次调用BeginSend() ,则可以确保发送将按照调用它们的顺序离开机器。

  • If you call BeginSend() from several threads, there is no guarantee of order unless you use some other blocking mechanism to force the actual calls to occur in some specific order. 如果从多个线程调用BeginSend() ,除非使用其他阻塞机制强制实际调用以某种特定顺序发生,否则无法保证顺序。 Each call however will send its data properly in one contiguous stream of network bytes. 然而,每个呼叫将在一个连续的网络字节流中正确地发送其数据。

I found a smiliar post on the MSDN forum which seems to answer to your question. 在MSDN论坛上发现了一个熟悉的帖子,它似乎回答了你的问题。

  1. You can queue multiple BeginSends at the same time. 您可以同时排队多个BeginSends。 You don't need to lock 你不需要锁定

Edit: 编辑:

Even more interesting informations: 更有趣的信息:

If you scroll down a bit in the Remark section of the MSDN doc BeginSend(), you will find interesting use of callback methods that could be relevant for you. 如果在MSDN doc BeginSend()的“ 备注”部分向下滚动一下,您会发现可能与您相关的回调方法的有趣用法。

[...] If you want the original thread to block after you call the BeginSend method, use the WaitHandle.WaitOne method. [...]如果您希望在调用BeginSend方法后阻止原始线程,请使用WaitHandle.WaitOne方法。 [...] [...]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM