我正在编写一个由一个调度程序线程和N个工作线程组成的C程序,其负责如下所述:
调度员线程: 在TCP端口上侦听; 在该端口上重复执行epoll_wait(); 建立连接时,接受它并将新的文件描述符(即“accept”函数返回的内容)传递给N个工作线程之一;
工作线程: 在每个新连接上,重复读取,直到没有收到数据; 使用作为参数接收的所有数据来调用解码函数,该函数将数据解码为消息结构(即RTSP消息);
我不知道的是,如果工作线程读取的数据不完整,我应该缓存它,这意味着我应该维护一个全局列表来缓存未使用的数据(即已接收但不是完整消息,因此尚未使用)对于每个连接?
答案 0 :(得分:0)
那么,你可以做的是维护一个固定大小的缓冲区,用于接收消息。整个消息和缓冲区的大小应该相同。 每次通过套接字描述符收到消息时,都可以检查并查看大小是否匹配。如果没有,你可以:
希望这有帮助。
答案 1 :(得分:0)
是否需要缓存数据取决于数据长度,连接数和内存大小。 例如,假设我们使用HTTP,正常的HTTP头应该小于4096字节,如果客户端使用POST方法,我们可以解析“Content-Length”,如果Content-Length太大,我们可以缓存帖子中的数据临时文件。
答案 2 :(得分:0)
如果你使用每个插槽的一个工作器,我想没有问题,你只是阻塞,直到你得到所有的消息..我假设这不是你的情况。
如果您使用worker以非阻塞方式处理多个套接字,则可以使用此方法:
开始以预定的缓冲区大小读取数据。 (尝试将缓冲区的大小与消息的最大可能长度相匹配,这样可以保存副本)。
确定总消息长度(来自协议标题)并计算继续阅读以完成整个消息所需的数量。在这种情况下,您可能已经读过“太多”,因此您应该为“下一个”消息分配另一个缓冲区,如果您想要更通用,您可以保留n个这样的缓冲区(基于最小的消息长度和指定的缓冲区来读取)。 您也可以选择始终只读取标题并从那里继续(这将确保您不会阅读太多),但这将更加浪费(每条消息需要两次读取)。
如果消息被完全读取,请对其进行处理,否则,保留缓冲区和此消息的字节数,然后通过套接字(您的epool)再次循环。
在下一次处理同一个套接字时,您将检查当前是否有部分消息,并从上次完成的位置继续读取同一个缓冲区。你需要在这里阅读下一个x字节,你需要准备好少于你期望的。 在这里,您还可以添加一个优化,一次性读取此套接字上的所有内容(保留在缓冲区中)(不仅是剩下的x个字节,还可以节省一些系统调用)。如果你这样做,你需要使用向量(readv()或类似的)。
如果没有优化的东西,处理起来非常简单。
答案 3 :(得分:0)
全球名单?你为什么需要这样的东西?缓冲区/缓冲区数组/缓冲区链接列表/缓冲区 - 应该是套接字对象的成员或引用/来自它的任何内容。如果必须将数据解析并阻塞到某种应用协议单元中,那么,是的,“剩余”数据必须被隔离,以便它可以构成下一个APU的一部分。复制它或允许每个缓冲区具有“起始索引”,该索引不一定必须为0。