首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >实现基于线路的网络工作者类的正确方法是什么

实现基于线路的网络工作者类的正确方法是什么
EN

Stack Overflow用户
提问于 2011-04-27 16:51:27
回答 3查看 234关注 0票数 1

我正在构建一个IRC客户端,并且想要一个IRC独立的网络类,它只是在客户端和服务器之间发送和接收线路。发送线路是可以的,但我不知道实现侦听器线程的好方法。我尝试过的所有方法都是有效的,但都有我无法绕过的缺陷。

我的第一个方法是创建一个名为_readerStreamReader,使用TcpClient.GetStream()作为基础,然后执行一个_reader.ReadLine()。这具有如下优点:后台监听器线程自动停止,直到接收到行为止。问题是,当我断开并停止侦听器线程(或者应用程序只是退出)时,我不确定它对垃圾回收等有多好,因为具有等待ReadLine()的线程会被终止。线程是否会成为孤立线程,并以某种方式留在后台窃取资源?

我的第二个方法是基于相同的TcpClient.GetStream()创建一个名为_readerNetworkStream,并创建一个循环来检查_reader.DataAvailable,如果while循环为false,则执行continue,否则将字节推入StringBuilder中,然后立即检查\r\n并提取所有整行。这在数据检索上产生了与ReadLine相同的效果,但是我不喜欢常量_reader.DataAvailable循环。在我的核心i5处理器上,它不需要任何处理器,但在我功能更强大的i9笔记本电脑上,它经常窃取一个虚拟i5。Thread.Sleep(1)“解决”了这个问题,但看起来像是一个肮脏的修复,互联网上的许多文章都将其归类为代码气味。

那么什么才是正确的解决方案呢?

EN

回答 3

Stack Overflow用户

发布于 2011-04-28 00:56:37

如果您正在中止侦听器线程,那么这是不好的。但是,如果应用程序退出(或者关闭底层套接字),那么就没有问题了。

列出大多数其他的,我不推荐轮询。我建议一种使用异步读写的解决方案,尽管编程要困难得多。

票数 1
EN

Stack Overflow用户

发布于 2011-04-29 21:09:43

这里有一些东西可以让你继续下去。

请注意,在构建消息时使用string效率不是很高。但它让一切变得更具可读性。

代码语言:javascript
复制
public abstract class LineBasedChannel
{   
    Socket _socket;
    string _inbuffer = string.Empty;
    Encoding _encoding;
    byte[] _buffer = new byte[8192];

    public LineBasedChannel(Socket socket)
    {
        _socket = socket;
        _encoding = Encoding.ASCII;
        _sb = new StringBuilder();
    }

    public void Start()
    {
        _socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None,OnRead, null);
    }

    public void OnRead(IAsyncResult res)
    {
        var bytesRead = _socket.EndReceive(res);
        if (bytesRead == 0)
        {
            HandleDisconnect();
            return;
        }

        _inbuffer += _encoding.GetString(_buffer, 0, bytesRead);
        _socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None,OnRead, null);

        while (true)
        {
            int pos = _inbuffer.IndexOf("\r\n");
            if (pos == -1)
                break;

            OnReceivedLine(_inbuffer.SubString(0, pos+2);
            _inbuffer = _inbuffer.Remove(0,pos+1);
        }
    }

    protected abstract void OnReceivedLine(string line);
}

public class IrcTcpChannel : LineBasedChannel
{
    protected override void OnReceivedLine(string line)
    {
        var cmd = new IrcCommand();
        cmd.Channel = line.SubString(x,y);
        cmd.Message = line.SubString(z,a);
        CommandReceived(this, new IrcCommandEventArgs(cmd));
    }

    public event EventHandler<IrcCommandEventArgs> CommandReceived = delegate {};
}

还要注意的是,我没有处理该代码中的任何异常,这是必须的。异步方法中任何未处理的异常都将终止您的应用程序。

票数 0
EN

Stack Overflow用户

发布于 2015-08-19 16:40:18

老问题,这个问题一定很久以前就解决了。无论如何,它看起来非常像更老的问题c# - What is a good method to handle line based network I/O streams? - Stack Overflow

如果是这样的话,那里的答案应该是解决方案的一部分。基本上,它是一个提供返回IEnumerable<string>Process(byte[])方法的类,它保持了尚未形成完整行的部分内容的状态。

使用它将允许分离关注点。只要读取可用的数据即可。每次读取一个块,将它输入到该方法中,您就会得到完全形成的行。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5801499

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档