我遇到了这个与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
答案 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
。是这样的吗?