异步TCP读取时发生Stackoverflow

本文关键字:Stackoverflow TCP 读取 异步 | 更新日期: 2023-09-27 18:10:14

最后一个适合这个网站的问题。

我有一个。net TCP服务器。这是我的第一个服务器,它工作得很好。客户端的加入,被管理,可以加入聊天室等。然而,大约30分钟后,在建立了一个客户端后,我得到了一个系统。在NetworkStream.ReadAsync期间发生StackOverflowException。我完全不知道这是什么问题。这是常事。

下面是关于我的TCP服务器的Client类的重要细节,当一个客户端加入时,一个新的Client被创建。

    public class Client {
        public TcpClient tcpClient;
        public NetworkStream stream;
        public CancellationTokenSource cts = new CancellationTokenSource();
        private byte[] readBuffer = new byte[1024];
        private StringBuilder receiveString = new StringBuilder();

        public Client(TcpClient tcpClient) {
            this.tcpClient = tcpClient;
            this.stream = this.tcpClient.GetStream();
        }
        public void StartReadAsync(){
            ReadAsync(cts.Token);
        }
        private async Task ReadAsync(CancellationToken ct) {
          // Stackoverflow exception occurs on next line after 20-30 mins
            int amountRead = await stream.ReadAsync(readBuffer, 0, readBuffer.Length, ct);
            if (amountRead > 0) {
                string message = Encoding.UTF8.GetString(readBuffer, 0, amountRead);
                receiveString.Append(message);
                Console.WriteLine("Client " + name + " sent: " + message);
                if (receiveString.ToString().IndexOf(eof) > -1) {
                    // Full message received, otherwise keep reading
                    if (OnClientRead != null)
                        OnClientRead(this, new SocketEventArgs(this, receiveString.ToString()));
                    receiveString.Clear();
                }
            }
            ReadAsync(ct);
        }
    }

异步TCP读取时发生Stackoverflow

你正在做一个可重入调用,ReadAsync再次调用ReadAsync,所以是的,你将以一个StackOverflow异常结束。

把你的代码改成:

public class Client 
{
    public TcpClient tcpClient;
    public NetworkStream stream;
    public CancellationTokenSource cts = new CancellationTokenSource();
    private byte[] readBuffer = new byte[1024];
    private StringBuilder receiveString = new StringBuilder();

    public Client(TcpClient tcpClient) {
        this.tcpClient = tcpClient;
        this.stream = this.tcpClient.GetStream();
    }
    public async void StartReadAsync(){
        while(await ReadAsync(cts.Token));
    }
    private async Task<bool> ReadAsync(CancellationToken ct) 
    {
        try
        {
            int amountRead = await stream.ReadAsync(readBuffer, 0, readBuffer.Length, ct);
            if (amountRead > 0)
            {
                string message = Encoding.UTF8.GetString(readBuffer, 0, amountRead);
                receiveString.Append(message);
                Console.WriteLine("Client " + name + " sent: " + message);
                if (receiveString.ToString().IndexOf(eof) > -1)
                {
                    // Full message received, otherwise keep reading
                    if (OnClientRead != null)
                        OnClientRead(this, new SocketEventArgs(this, receiveString.ToString()));
                    receiveString.Clear();
                }
                return true;
            }
            return false;
        }
        catch { return false; }
    }
}