c# - 直到 socket.Close 才收到 Windows socket.Send 数据

标签 c# .net sockets send

我正在开发一个异步接受 TCP 连接 (BeginAccept/EndAccept) 和数据 (BeginReceive/EndReceive) 的服务器应用程序。该协议(protocol)要求在发送下一条消息之前,只要发现 EOM 字符就发送 ACK。接受和接收正在工作,但发送应用程序没有收到 ACK(同步发送)。

    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 返回正确的字节数,但在处理套接字之前不会收到数据。

欢迎提出建议。

最佳答案

  • 你不应该做任何与异步完成例程同步的事情。在负载下,您最终可能会劫持线程池中的所有 IO 完成线程并严重损害性能,甚至包括完全 IO 死锁。所以不要从异步回调中同步发送 ACK。
  • 使用前导码的协议(protocol)和格式比使用终止符的协议(protocol)和格式更容易管理。 IE。在固定大小的消息头中写入消息的长度,而不是检测终止符\0x13。当然,如果协议(protocol)一开始就在您的控制之下,这就适用。

至于您的问题,您没有说明您发布的相同代码是否也在客户端。

关于c# - 直到 socket.Close 才收到 Windows socket.Send 数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2269133/

相关文章:

c# - 没有 DI 的单元测试遗留代码

c# - 将unicode转换为正确的单词

c# - 是否可以使用 C# 开发 Android 应用程序?

c++ - 由于错误代码10093,C++程序无法连接到服务器

sockets - Phoenix Channels - 每个插槽有多个 channel

c# - 如何在 UWP (Windows 10) 中更改所选 ListView 项目的突出显示颜色

c# - 打开实例委托(delegate)给值类型

c# - iTextSharp 文件操作和显示到 FileStreamResults

c# - 第一次反序列化比后续反序列化花费的时间要长得多

macos - 内核控制API可以支持多个同时的客户端连接吗?