Windows socket. Send data is not accepted until the socket. Close

I am developing a server application that accepts TCP connections (BeginAccept / EndAccept) and data (BeginReceive / EndReceive) asynchronously. The protocol requires the ACK to be sent whenever the EOM symbol is found before it sends the next message. Receive and receive work, but the sending application does not receive the ACK (sent synchronously).

private void _receiveTransfer(IAsyncResult result) { SocketState state = result.AsyncState as SocketState; int bytesReceived = state.Socket.EndReceive(result); if (bytesReceived == 0) { state.Socket.Close(); return; } state.Offset += bytesReceived; state.Stream.Write(state.Buffer, 0, bytesReceived); if (state.Buffer[bytesReceived - 1] == 13) { // process message Messages.IMessage message = null; try { var value = state.Stream.ToArray(); // do some work var completed = true; if (completed) { // send positive ACK var ackMessage = string.Format(ack, message.TimeStamp.ToString("yyyyMMddhhmm"), message.MessageType, message.Id, "AA", message.Id); var buffer = ASCIIEncoding.ASCII.GetBytes(ackMessage); int bytesSent = state.Socket.Send(buffer, 0, buffer.Length, SocketFlags.None); } else { // send rejected ACK var ackMessage = string.Format(ack, message.TimeStamp.ToString("yyyyMMddhhmm"), message.MessageType, message.Id, "AR", message.Id); state.Socket.Send(ASCIIEncoding.ASCII.GetBytes(ackMessage)); } } catch (Exception e) { // log exception // send error ACK if (message != null) { var ackMessage = string.Format(ack, DateTime.Now.ToString("yyyyMMddhhmm"), message.MessageType, message.Id, "AE", message.Id); state.Socket.Send(ASCIIEncoding.ASCII.GetBytes(ackMessage)); } } } state.Socket.BeginReceive(state.Buffer, 0, state.Buffer.Length, SocketFlags.None, new AsyncCallback(_receiveTransfer), state); } 

State.Socket.Send returns the correct number of bytes, but no data is received until the socket is deleted.

Suggestions are welcome.

+4
source share
4 answers
  • you should not do anything synchronous from asynchronous termination procedures. Under load, you can end up capturing all I / O completion threads from the thread pool and drastically reduce performance, until IO is completely blocked. Therefore, do not send the ACK synchronously with the asynchronous callback.
  • Protocols and formats that use preambles make it easier to manage those that use terminators. I.e. write the message length in the message header of a fixed size, as opposed to detecting the terminator \ 0x13. Of course, this applies if the protocol is under your control to begin with.

As for your question, you did not indicate whether the same code as you is also on the client side.

+2
source

How long have you been giving this? The network stack may buffer, and this may delay transmission. From MSDN :

To improve network efficiency, the base system can delay transfers to a significant amount of outgoing data. The successful completion of the sending method means that the system has room for data to send over the network.

You might want to flush using the IOControl method.

change

In fact, flushing IOControl will destroy the buffer. You can check the β€œTwo Generals Problem” to see if your protocol has any inherent problems.

0
source

try setting the socket option TCP_NODELAY

0
source

Did the NoDelay property NoDelay to true on the socket? If set to false (default), data is buffered up to 200 milliseconds before being sent. The reason is to reduce network traffic by limiting the number of packets sent. Setting NoDelay to true will force data to be sent earlier.

0
source

Source: https://habr.com/ru/post/1301378/


All Articles