当前位置: 首页 > 知识库问答 >
问题:

异步TCP读取期间的Stackoverflow

翁阳曜
2023-03-14

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

    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);
        }
    }

共有1个答案

欧阳正德
2023-03-14

您正在执行一个重入调用,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; }

    }
}
 类似资料:
  • 异步Tcp客户端 串行发包 use AsyncTcp; $tcp = new AsyncTcp('127.0.0.1', 9501); $tcp->setTimeout(2); //串行发送 $res = (yield $tcp->call('hello server!')); $res = (yield $tcp->call('hello serv

  • 问题内容: 当有字符可用时,是否有一种优雅的方法来触发事件?我想避免投票。 问题答案: 您将必须创建一个单独的线程以阻止读取,直到有可用的线程为止。 如果您不想实际消耗输入,则必须用内部缓冲区包装它,读入缓冲区,然后喊叫,并在要求输入时从缓冲区返回数据。 您可以这样解决:

  • 我读了SO的以下文章 字段读取同步和易失性之间的区别 发问者写道 同步的目的是确保此线程读取的acct.balance值是当前值,并且对acct.balance中对象字段的任何挂起写入也会写入主存。 最受欢迎的答案: 你是正确的。 请研究此代码: 在我的电脑上,这个程序不会终止。 因此我认为 如果我更改volatile变量,我将在另一个线程中看到任何未完成的地方的实际值 我说得对吗?

  • 异步文件读写 读文件 use AsyncFile; $content = (yield AsyncFile::read(__ROOT__."runtime/test.txt")); 写文件 $res = (yield AsyncFile::write(__ROOT__."runtime/test.txt", "hello wordls!")); $res = (yi

  • 未来你可能会用 Redis 服务器或者其他的消息队列系统来作为 logstash broker 的角色。不过 Logstash 其实也有自己的 TCP/UDP 插件,在临时任务的时候,也算能用,尤其是测试环境。 小贴士:虽然 LogStash::Inputs::TCP 用 Ruby 的 Socket 和 OpenSSL 库实现了高级的 SSL 功能,但 Logstash 本身只能在 SizedQu

  • 问题内容: 我正在尝试在Go中创建服务器和客户端,我已经设法与服务器和客户端进行通信。但是我的问题是,在golang中读取的TCP是非阻塞的。我想知道的是,golang中的读取是否有可能像C中的读取一样被阻塞。谢谢 编辑: 这是服务器的源代码: 和我的客户: 问题答案: 可以返回部分数据。从该文档,“如果某些数据是可用的,但不是LEN(P)个字节,读取常规返回什么是可用的,而不是等待更多。” 无论