【问题标题】:How do you use C# NetworkStream ReadAsync() to only grab stuff between stx and etx?您如何使用 C# NetworkStream ReadAsync() 仅在 stx 和 etx 之间获取内容?
【发布时间】:2015-07-07 15:03:53
【问题描述】:

我正在尝试构建一个通过 TCP/IP 与另一个已完成的应用程序通信的新应用程序。这两个应用程序在彼此之间来回传递消息。这是我的新应用程序中的一些服务器代码,它们从完成的应用程序中读取内容:

public class AsyncService
{
    private IPAddress ipAddress;
    private int port;
    char[] STX = new char[] { '' };
    char[] ETX = new char[] { '' };
    NetworkStream networkStream;
    TcpClient tcpClient;
    private byte[] rawBuffer;

    private static readonly int RAWBUFFERSIZE = 2024;

    public AsyncService(int port)
    {
        this.port = port;
        string hostName = Dns.GetHostName();
        IPHostEntry ipHostInfo = Dns.GetHostEntry(hostName);
        rawBuffer = new byte[RAWBUFFERSIZE];
        this.ipAddress = IPAddress.Any;
        if (this.ipAddress == null)
        {
            throw new Exception("No IPv4 address for server");
        }
    }

    public async void Run()
    {
        TcpListener listener = new TcpListener(this.ipAddress, this.port);
        listener.Start();
        while (true)
        {
            try
            {
                tcpClient = await listener.AcceptTcpClientAsync();
                networkStream = tcpClient.GetStream();
                DoReadAsync(rawBuffer);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
        }
    }

    private void DoReadAsync(byte[] byteBuffer)
    {
        Task<int> t = networkStream.ReadAsync(byteBuffer, 0, byteBuffer.Length);
        t.ContinueWith((task, bytes) => OnReadCompleted((byte[])bytes, task.Result), byteBuffer, TaskContinuationOptions.OnlyOnRanToCompletion);
    }

    private void OnReadCompleted(byte[] byteBuffer, int length)
    {
        if (length == 0)
        {
            return;
        }

        string message = ASCIIEncoding.ASCII.GetString(byteBuffer);

        //...

        Array.Clear(byteBuffer, 0, byteBuffer.Length);
        DoReadAsync(byteBuffer);
    }

发送的每条消息都以 STX 字符开头,以 ETX 字符结尾。问题是有时我的新应用程序一次收到多条消息。例如,我可能会收到这样的消息:

[STX]123456789[ETX][STX]10111213141516171819[ETX]

我想编写我的代码,以便我只阅读直到遇到 ETX 字符。因此,我希望上面的示例是两条消息,但我不知道如何使用 ReadAsync() 来做到这一点。有谁知道我该怎么做?

【问题讨论】:

  • 这就是缓冲区的工作方式。您正在阅读缓冲区中的内容。它可能是一个完整的消息,两个消息,半个消息。你需要自己把它拼起来。
  • 如果您自己定义消息,通常更容易让前 4 个字节指定消息的长度,然后读取接下来的 x 个字节(由前四个字节指定),然后一旦你有读取该长度读取接下来的 4 个字节以获得下一个消息长度
  • 执行此操作的简单方法是切换到 SignalR。 :)
  • @StephenCleary 您能否提供有关在 asp .net 应用程序之外使用 signalR 的资源?
  • @Bruno: Here you go

标签: c# async-await task


【解决方案1】:

您基本上有 2 个选择。将整个流读入一个字符串,然后解析它,或者通过逐字节读取它并在到达“神奇”字节组合时停止来动态解析流。就个人而言,如果数据流不是很大,那么选项 1 将更容易实现 hth

【讨论】:

  • 这 2 个解决方案是否一般是好的(关于最佳实践),并且 STX/ETX 的东西是实现 tcp 套接字时要做的事情吗?这是一个真正的网络新手问题,根本不是批评者,因为我面临着同样的问题。
猜你喜欢
  • 2015-03-26
  • 2021-01-13
  • 1970-01-01
  • 2012-10-14
  • 2015-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多