我正在使用epoll工作linux服务器。我有这个代码来读取缓冲区
int str_len = read(m_events[i].data.fd, buf, BUF_SIZE);
if (str_len == 0) {
if (!removeClient(m_events[i].data.fd))
break;
close(m_events[i].data.fd);
} else {
char *pdata = buf;
pushWork(pdata);
}
buf被声明为
buf[BUF_SIZE]
pushWork函数声明如下
pushWork(char *pdata){
push pdata to the thread pool's queue
}
首先,我认为char * pdata = buf有问题,因为它只是指向缓冲区,只要有新数据进入缓冲区就会被覆盖。所以我需要memcpy吗?
另外,还有其他很好的方法可以在c ++中处理这个问题吗?这段代码有点样式我认为我有更好的方法在c ++中这样做。
答案 0 :(得分:2)
还有其他好办法吗? 这在c ++?这段代码有点像c 风格我觉得我有更好的方式 在c ++中执行此操作
就像我在你的一个previous questions中建议的那样,Boost.Asio库是事实上的C ++网络库。如果您正在编写C ++网络应用程序,我强烈建议您花一些时间阅读并研究这些示例。
答案 1 :(得分:0)
这种方式很糟糕,因为你只有一个buf,这意味着你一次只能有一个线程处理它,所以你没有使用它们应该被使用的线程。
你可以做的是malloc()一个缓冲区,将有效负载复制到该malloc缓冲区并将其传递给线程,并让线程在完成后释放该缓冲区。请务必释放它,否则会出现内存泄漏。
示例代码:
char * p;
p = (char *)malloc(str_len+1);
memcpy(p, buf, str_len+1);
pushWork(p); //free p inside, after use.
答案 2 :(得分:0)
你需要做一个memcpy(或类似的东西),除非你能做到这一点,以便在pushWork()返回后永远不需要(buf)中的数据。如果你能负担pushWork(),OTOH中缓冲区数据的所有处理,则不需要复制缓冲区。
另一个替代方案是每次通过epoll循环提前从堆中分配一个缓冲区,并将read()直接分配到该缓冲区而不是读入堆栈中的缓冲区......这样动态分配的缓冲区就会在事件循环继续进行其他事情后仍然可以使用。请注意,这样做会为可能的内存泄漏或内存耗尽打开大门,因此您需要小心避免这些问题。
就这样做的“C ++方式”而言,我确信有一些,但我不知道它们必然会改进你的程序。 C方式工作正常,为什么要修复未破坏的东西?
(另外需要注意的一点是:如果你使用非阻塞I / O,那么read()有时会读取并返回少于BUF_SIZE个字节,在这种情况下你需要逻辑来处理这种可能性。如果你正在使用阻塞I / O,OTOH,read()有时会长时间阻塞(例如,如果客户端机器已经只发送了一半的缓冲区),这将阻止你的epoll循环并使其无响应大概几分钟。这是一个更难处理的问题,这就是为什么我通常最终会使用非阻塞I / O,即使这样做更难以实现。