如何使用C#NetworkStream ReadAsync()只获取stx和etx之间的内容?

如何使用C#NetworkStream ReadAsync()只获取stx和etx之间的内容?,c#,async-await,task,C#,Async Await,Task,我正在尝试构建一个新的应用程序,通过TCP/IP与另一个完成的应用程序进行通信。这两个应用程序在彼此之间来回传递消息。以下是我的新应用程序中的一些服务器代码,用于从完成的应用程序中读取内容: public class AsyncService { private IPAddress ipAddress; private int port; char[] STX = new char[] { '' }; char[] ETX = new char[] { '' };

我正在尝试构建一个新的应用程序,通过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);
    }
公共类异步服务
{
私人IP地址;
专用int端口;
char[]STX=新的char[]{''};
char[]ETX=新的char[]{''};
网络流;
TCP客户机TCP客户机;
专用字节[]缓冲区;
私有静态只读int-RAWBUFFERSIZE=2024;
公共异步服务(int端口)
{
this.port=端口;
字符串hostName=Dns.GetHostName();
IPHostEntry ipHostInfo=Dns.GetHostEntry(主机名);
rawBuffer=新字节[RAWBUFFERSIZE];
this.ipAddress=ipAddress.Any;
if(this.ipAddress==null)
{
抛出新异常(“服务器没有IPv4地址”);
}
}
公共异步无效运行()
{
TcpListener listener=新的TcpListener(this.ipAddress,this.port);
listener.Start();
while(true)
{
尝试
{
tcpClient=await listener.AcceptTcpClientAsync();
networkStream=tcpClient.GetStream();
DoReadAsync(rawBuffer);
}
捕获(例外情况除外)
{
Debug.WriteLine(例如消息);
}
}
}
专用void DoReadAsync(字节[]byteBuffer)
{
Task t=networkStream.ReadAsync(byteBuffer,0,byteBuffer.Length);
t、 ContinueWith((任务,字节)=>OnReadCompleted((字节[])字节,task.Result),byteBuffer,TaskContinuationOptions.OnlyOnRanToCompletion);
}
私有void OnReadCompleted(字节[]byteBuffer,整数长度)
{
如果(长度==0)
{
返回;
}
string message=ascienceoding.ASCII.GetString(byteBuffer);
//...
Array.Clear(byteBuffer,0,byteBuffer.Length);
DoReadAsync(byteBuffer);
}
发送的每条消息前面都有一个STX字符,结尾是一个ETX字符。问题是,有时我的新应用程序一次会收到多条消息。例如,我可能会收到如下消息:

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


我想让我的代码只读到一个ETX字符。因此,我希望上面的示例是两条消息,但我不知道如何使用ReadAsync()实现这一点。有人知道我该怎么做吗?

你基本上有两个选择。将整个流读入字符串,然后对其进行解析,或者通过逐字节读取并在到达“神奇”字节组合时停止对流进行动态解析。就我个人而言,如果数据流不是海量的,那么选项1将更容易实现
hth

这就是缓冲区的工作方式。您正在读取缓冲区中的内容。它可能是一整条消息、两条消息、半条消息。您需要自己处理将其拼合在一起的问题。如果您自己定义消息,则通常更容易让前4个字节指定消息的长度,然后读取下一个x字节(由前四个字节指定)然后,一旦您读取了该长度,请读取接下来的4个字节以获取下一个消息长度。简单的方法是切换到SignalR.:@StephenCleary您能提供有关在asp.net应用程序之外使用SignalR的资源吗?@Bruno:这两种解决方案一般来说是好的吗(关于最佳实践)在实现tcp套接字时,STX/ETX的东西是要做的吗?这是一个真正的网络neewbie问题,而不是一个批评家,因为我面临着同样的问题。