Are Asynchronous writes to a socket thread safe?

2019-04-20 05:29发布

Consider the Socket.BeginSend() method. 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?

2条回答
霸刀☆藐视天下
2楼-- · 2019-04-20 06:07

.NET Socket instances are not thread-safe in that simultaneous calls to some methods (the same or different ones) may cause inconsistent state. However, the BeginSend() and BeginReceive() methods are thread-safe with respect to themselves.

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. 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()). 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:

  1. The 8K is a "nominal size" number, and the buffer may shrink and grow somewhat

  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

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.

  • 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. Each call however will send its data properly in one contiguous stream of network bytes.

查看更多
兄弟一词,经得起流年.
3楼-- · 2019-04-20 06:09

I found a smiliar post on the MSDN forum which seems to answer to your question.

  1. You can queue multiple BeginSends at the same time. 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.

[...] If you want the original thread to block after you call the BeginSend method, use the WaitHandle.WaitOne method. [...]

查看更多
登录 后发表回答