C:使用选择呼叫,当我阅读时,如何跟踪数据? [英] C: Using a select call, when I am reading, how do I keep track of the data?

查看:66
本文介绍了C:使用选择呼叫,当我阅读时,如何跟踪数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,我以前从未使用过C(主要是Java,这就是为什么您会发现我写一些朴素的C代码的原因).我正在用C语言编写一个简单的命令解释器.

First of all, I've never worked with C before (mostly Java which is the reason you'll find me write some naive C code). I am writing a simple command interpreter in C. I have something like this:

//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字节缓冲区,我将如何去做呢?我是否跟踪哪个客户端给了我什么数据并将其附加到某个缓冲区?我的意思是,使用诸如二维数组之类的东西?

Now if I'm looking at something like a long paragraph of commands, it is obvious that a 256 byte buffer will not be able to get the entire command. For the time being, I'm using a 2056 byte buffer to get the entire command. But if I want to use the 256 byte buffer, how would I go about doing this? Do I keep track of which client gave me what data and append it to some buffer? I mean, use something like two dimensional arrays and such?

推荐答案

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

Yes, the usual approach is to have a buffer of "data I've received but not processed" for each client, large enough to hold the biggest protocol message.

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

You read into that buffer (always keeping track of how much data is currently in the buffer), and after each read, check to see if you have a complete message (or message(s), since you might get two at once!). If you do, you process the message, remove it from the buffer and shift any remaining data up to the start of the buffer.

大致符合以下条件:

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 */
}

顺便说一句,您应该检查errno == EINTR是否select()返回-1,然后再次循环-这不是致命错误.

By the way, you should check for errno == EINTR if select() returns -1, and just loop around again - that's not a fatal error.

这篇关于C:使用选择呼叫,当我阅读时,如何跟踪数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆