2014-03-06 45 views
0

我遇到了这个tcp服务器的例子,随Altera Nios II处理器一起提供,我没有得到关于处理rx_buffer的部分。这个tcp套接字代码如何处理rx缓冲区?

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

该部分在缓冲区处理完毕后将其从缓冲区中移除。您发布的代码从不使用缓冲区中的数据存储,但sss_exec_command函数将在收到换行符后。该函数传递连接,所以它可以增加读取位置的大小。

使用数据后,缓冲区管理部分回收空间。留在缓冲区中的数据量是写入位置和读取位置之间的差异。这些数据从写入位置移动到缓冲区的开始位置,然后读写指针被更新为新的位置。读取位置设置为缓冲区的开始位置,写入位置减少data_used,这是缓冲区开始和读取指针之间的原始差异,即所用数据量。

+0

你说得对。我完全错过了它。谢谢! – dsell002

1

假设代码实际工作,然后data_used = conn->rx_rd_pos - conn->rx_buffer暗示rx_rd_pos正在更改;当代码已经使用写入缓冲区的数据时(它被写入rx_wr_pos并从rx_rd_pos消耗),这将被改变。这意味着sss_exec_command(conn)正在调整conn。是这样吗?