这个tcp套接字代码如何处理rx缓冲区?

时间:2014-03-06 19:50:54

标签: c tcp

我遇到了这个与Altera Nios II处理器一起提供的tcp服务器示例,我没有得到有关处理rx_buffer的部分。

server.h

typedef struct SSS_SOCKET {
    enum {
        READY, COMPLETE, CLOSE
    } state;
    int fd;
    int close;
    INT8U rx_buffer[SSS_RX_BUF_SIZE];
    INT8U *rx_rd_pos; /* position we've read up to */
    INT8U *rx_wr_pos; /* position we've written up to */
} SSSConn;

server.c

int data_used = 0, rx_code = 0;
INT8U *lf_addr;

conn->rx_rd_pos = conn->rx_buffer;
conn->rx_wr_pos = conn->rx_buffer;

printf("[sss_handle_receive] processing RX data\n");

while (conn->state != CLOSE) {
    /* Find the Carriage return which marks the end of the header */
    lf_addr = strchr(conn->rx_buffer, '\n');

    if (lf_addr) {
        /* go off and do whatever the user wanted us to do */
        sss_exec_command(conn);
    }
    /* No newline received? Then ask the socket for data */
    else {
        rx_code = recv(conn->fd, conn->rx_wr_pos,
                SSS_RX_BUF_SIZE - (conn->rx_wr_pos - conn->rx_buffer) -1, 0);

        if (rx_code > 0) {
            conn->rx_wr_pos += rx_code;

            /* Zero terminate so we can use string functions */
            *(conn->rx_wr_pos + 1) = 0;
        }
    }

    /* 
     * When the quit command is received, update our connection state so that
     * we can exit the while() loop and close the connection
     */
    conn->state = conn->close ? CLOSE : READY;

    /* Manage buffer */
    data_used = conn->rx_rd_pos - conn->rx_buffer;
    memmove(conn->rx_buffer, conn->rx_rd_pos,
            conn->rx_wr_pos - conn->rx_rd_pos);
    conn->rx_rd_pos = conn->rx_buffer;
    conn->rx_wr_pos -= data_used;
    memset(conn->rx_wr_pos, 0, data_used);
}

具体来说,我没有看到data_used变量的用途。 rx_rd_pos指向rx_buffer并且似​​乎没有任何操作,那么它们将如何不同?事实上,在Manage buffer下似乎唯一发生的事情是将数据复制到rx_buffer。我确定我错过了一些简单的东西,但我似乎无法看到它。

感谢您提前提供任何帮助。

编辑:这是 sss_exec_command()功能。

void sss_exec_command(SSSConn* conn) {
int bytes_to_process = conn->rx_wr_pos - conn->rx_rd_pos;
INT8U tx_buf[SSS_TX_BUF_SIZE];
INT8U *tx_wr_pos = tx_buf;

INT8U error_code;

/*
 * "SSSCommand" is declared static so that the data will reside 
 * in the BSS segment. This is done because a pointer to the data in 
 * SSSCommand
 * will be passed via SSSLedCommandQ to the LEDManagementTask.  
 * Therefore SSSCommand cannot be placed on the stack of the 
 * SSSSimpleSocketServerTask, since the LEDManagementTask does not 
 * have access to the stack of the SSSSimpleSocketServerTask.
 */
static INT32U SSSCommand;

SSSCommand = CMD_LEDS_BIT_0_TOGGLE;

while (bytes_to_process--) {
    SSSCommand = toupper(*(conn->rx_rd_pos++));

    if (SSSCommand >= ' ' && SSSCommand <= '~') {
        tx_wr_pos += sprintf(tx_wr_pos,
                "--> Simple Socket Server Command %c.\n",
                (char) SSSCommand);
        if (SSSCommand == CMD_QUIT) {
            tx_wr_pos += sprintf(tx_wr_pos,
                    "Terminating connection.\n\n\r");
            conn->close = 1;
        } else {
            error_code = OSQPost(SSSLEDCommandQ, (void *) SSSCommand);

            alt_SSSErrorHandler(error_code, 0);
        }
    }
}

send(conn->fd, tx_buf, tx_wr_pos - tx_buf, 0);

return;

}

以下答案是正确的。我在命令函数中错过了rx_rd上的指针算法:P

2 个答案:

答案 0 :(得分:2)

该部分一旦处理完就从缓冲区中删除数据。您发布的代码从不使用缓冲区中的数据存储,但在收到换行符后,sss_exec_command函数将使用。该函数被传递给连接,因此它可以通过它使用的多少来增加读取位置。

使用数据后,缓冲区管理部分回收空间。缓冲区中剩余的数据量是写入和读取位置之间的差异。这么多数据从写入位置移动到缓冲区的开始,然后读取和写入指针被更新到它们的新位置。读取位置设置为缓冲区的起始位置,写入位置递减data_used,这是缓冲区开始和读取指针之间的原始差异,即使用的数据量。

答案 1 :(得分:1)

假设代码确实有效,那么data_used = conn->rx_rd_pos - conn->rx_buffer意味着rx_rd_pos正在改变;当代码消耗了写入缓冲区的数据(它写在rx_wr_pos并从rx_rd_pos消耗)时,这将被更改。这意味着sss_exec_command(conn)正在调整conn。是这样的吗?