C:使用选择调用,当我阅读时,我如何跟踪数据?

标签 c networking select buffer

首先,我以前从未使用过 C(主要是 Java,这就是您会发现我编写一些天真的 C 代码的原因)。我正在用 C 编写一个简单的命令解释器。我有这样的东西:

//Initialization code

if (select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1) {
    perror("Select dead");
    exit(EXIT_FAILURE);
}

....
....
//Loop through connections to see who has the data ready
//If the data is ready
if ((nbytes = recv(i, buf, sizeof(buf), 0)) > 0) {
     //Do something with the message in the buffer
}

现在,如果我正在查看类似一长段命令的内容,很明显 256 字节的缓冲区将无法获取整个命令。目前,我正在使用 2056 字节缓冲区来获取整个命令。但是如果我想使用 256 字节缓冲区,我该怎么做呢?我是否跟踪哪个客户给了我什么数据并将其附加到某个缓冲区?我的意思是,使用二维数组之类的东西?

最佳答案

是的,通常的方法是为每个客户端设置一个“我已收到但未处理的数据”的缓冲区,其大小足以容纳最大的协议(protocol)消息。

您读入该缓冲区(始终跟踪缓冲区中当前有多少数据),每次读取后,检查是否有完整的消息(或消息),因为您可能会在一次!)。如果这样做,您将处理该消息,将其从缓冲区中移除并将所有剩余数据移动到缓冲区的开头。

大致是这样的:

for (i = 0; i < nclients; i++)
{
    if (!FD_ISSET(client[i].fd, &read_fds))
        continue;

    nbytes = recv(client[i].fd, client[i].buf + client[i].bytes, sizeof(client[i].buf) - client[i].bytes, 0);

    if (nbytes > 0)
    {
        client[i].bytes += nbytes;

        while (check_for_message(client[i]))
        {
            size_t message_len;

            message_len = process_message(client[i]);
            client[i].bytes -= message_len;
            memmove(client[i].buf, client[i].buf + message_len, client[i].bytes);
        }
    }
    else
        /* Handle client close or error */
}

顺便说一下,如果 select() 返回 -1,您应该检查 errno == EINTR,然后再次循环 - 这不是 fatal error 。

关于C:使用选择调用,当我阅读时,我如何跟踪数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2159628/

相关文章:

对 c 中的 vector 的好奇心

javascript - Safari/Firefox/浏览器无法就选择元素大小达成一致

java - 局域网上的点对点发现

mysql - 连接多个表时避免重复条目 (MySQL)

jakarta-ee - Struts 2-s :select using Map

c - MPI_收集接收缓冲区中的垃圾 (MPI+C)

c - c编译器如何为结构分配内存?

c - 基于汇编32位(x86)编写C代码

linux - telnet 127.0.0.1 peer 不是 127.0.0.1

python - 从网络导入模块