如何使用C#NetworkStream ReadAsync()只获取stx和etx之间的内容?
我正在尝试构建一个新的应用程序,通过TCP/IP与另一个完成的应用程序进行通信。这两个应用程序在彼此之间来回传递消息。以下是我的新应用程序中的一些服务器代码,用于从完成的应用程序中读取内容:如何使用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[] { '' };
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问题,而不是一个批评家,因为我面临着同样的问题。