I am building a fairly complex client-server system, so I would like to be able to apply multithreading, say, on the client, send heartbeat on one stream, and send a command to the server on another stream, while using only one socket. But is this a normal solution?

To begin, let me explain what kind of confusion I am talking about.

So, pseudocode is what I send:

send("123456"); // Поток 1 send("ABCDEF"); // Поток 2 

I know that in the end this can come to the receiving party:

 ABCDEF 123456 

That is, I understand that the order of the messages that I send may be confused .
When I tried to create a lot of threads, I watched this , so it really is.
And I'm not afraid of that.


But one person on the forum, if I understood him correctly, claims that everything is still worse.
He says that the bytes themselves in messages may be confused , that is, it can come like this:

 ABC45F 123DE6 

Is it true?
When I tried to create a lot of threads, I did NOT observe this , there were many messages, but in none of them the bytes were mixed with the bytes from other messages.
But I will not hope at random, so just in case I ask.

Operating system :
Windows, different versions and bitness, but only Windows, both on the server and on the clients.

  • It would be possible to add a link where someone says it. - Qwertiy
  • one
    Most likely, this will be written in the documentation for the class that you use as a wrapper for the socket. Usually, it’s you who should take care of avoiding simultaneous use. - VladD
  • @VladD in the classroom what? just a stupid wrapper for the system function send, that's why I wrote "send / write". I'm interested in send, if it does not mix bytes, then in .NET classes, etc. will not mix too - KG
  • one
    @Qwertiy here is the link to whoever says it. cyberforum.ru/win-api/thread1856826-page3.html#post9881925 He still insists on it. This is not a misunderstanding. - KG
  • 2
    without answering the question itself : you do not need to do this in different threads, single writer-systems almost always demonstrate the best performance and clarity to the developer. make a queue that some socket-writer will read; in any case, your ultimate goal is the sequential transfer of different packets to the socket, and this task itself cannot be distributed (because it assumes this sequential transfer). - etki

1 answer 1

You do not need multithreading for this if you just use async/await . In this case, all messages will be sent in one thread. It looks something like this:

 AsyncLock socketLock = new AsyncLock(); async Task SendData(byte[] data, CancelltionToken ct) { using (await socketLock.LockAsync(ct)) await networkStream.WriteAsync(data, 0, data.Length, ct); } async Task SendHeartbeat(CancelltionToken ct) { try { while (true) { await Task.Delay(TimeSpan.FromSeconds(10), ct); ct.ThrowIfCancellationRrequested(); await SendData(heartbitBytes, ct); } } catch (OperationCancelledException) { } } 

Well, sending a regular message is simple:

 await SendData(messageBytes, ct); 

As a result, we did without multithreading.

The AsyncLock class AsyncLock taken here: https://github.com/StephenCleary/AsyncEx/wiki/AsyncLock


Essentially the question: if the documentation says that you cannot write anything from two streams to the socket / NetworkStream / at the same time, then it is better not to try to figure out under what conditions this restriction can be circumvented, because in the next version of the language / libraries such a hack not work. Stay on the bright side of power!

  • In the next version of the OS then. And thanks, but some third-party class for such nonsense ... I better implement it myself, even without async await, I also have to rewrite the client on Delphi 7, where there are no async await, it is possible on the server C # and even .NET 4 ... - KG
  • @KG: Well, how do you forget about asynchronous locking with your hands? This is nontrivial. - VladD
  • @KG: Why next OS? You have XP, or what? Starting with the seven, should go fine. - VladD
  • yes, I don’t know yet how I forget about it, it’s not necessary to bother, you can just make an event in the "writer" stream and call it from other threads. As for the next version, oooh ... well, clearly what I meant by the word "because in the next version of the language / libraries such a hack might not work.", So not the OS language, what a boring right you are - KG
  • @KG: Well, if you think an event is easy to get along with, good luck. Well, maybe there is a less tedious explanatory. - VladD