使用 recv() 接收消息块
Using recv() to receive chunks of a message
我正在使用 WebSockets。我创建了一个小型测试客户端,它将消息拆分,然后逐块发送。例如这样的消息:
PROTOCOL HTTP ACTION UPDATE
可以发送为
PROTOC
然后作为一个块
OL HTT
作为另一个而不是在一个块中发送完整的消息作为 PROTOCOL HTTP ACTION UPDATE
这也是一种可能性。
所以我接收消息的方式必须反映这一点。目前,我不确定如何使用 recv
当一条消息被分成多个部分并发送时。
这就是我正在尝试的方法,但我不确定这是否是正确的方法。我应该在接收时始终将缓冲区的大小保持为 200 吗?我应该什么时候退出循环?
void recv_all(){
char rec_buffer[200]
while(1) {
ssize_t bytes_rec = recv(socket_fd, rec_buffer, sizeof(rec_buffer),0);
}
}
您可以使用调用 read()
的返回值,然后使用 strcat()
将消息的各个部分粘合在一起。
根据 OP,消息以 \r\n
结尾,这是一个如何将消息作为多个数据包读取的示例。
char *message = malloc( MAX_MSG_LEN +1 );
if( ! message )
{
perror( "malloc failed" );
exit( EXIT_FAILURE );
}
// implied else, malloc successful
recv_buf[0] = '[=10=]';
size_t msgLen = 0;
int done = 0;
while( msgLen < MAX_MSG_LEN && !done)
{
ssize_t byteCount = read( socket_fd, message, MAX_MSG_LEN );
if( ! byteCount )
{
// handle error of sender closing the socket
}
else if( byteCount < 0 )
{
// handle I/O error
}
else
{
if( msgLen+byteCount > sizeof( recv_buf ) )
{
// handle error of message too long
}
else
{
message[ byteCount ] = '[=10=]';
strcat( recv_buf, message );
msgLen += byteCount;
if( memcmp( recv_buf[msgLen-2], "\r\n", 2 ) == 0 )
{
done = 1;
}
}
}
}
free( message );
注意:我没有运行上面的例子,所以可能需要做一些调试。
(stream) 套接字处理字节流,而不是消息。因此,它们提供了一种在端点之间获取字节流的方法,仅此而已。如果您想要某种 'messages',您需要处理字节流以找到消息边界并自行将其分解为消息。
执行此操作的通常方法是使用缓冲区,例如 C FILE 对象或 C++ streambuf。您安排字节从套接字读取到缓冲区,然后检查缓冲区中是否有完整的消息,通常是通过查找消息 terminator/boundary 标记(例如 \r\n 或只是 \ n).如果存在,则(仅)从缓冲区中删除消息。
在 C 语言中使用 POSIX 很容易做到——您可以使用 fdopen
打开一个带有套接字描述符的文件,然后使用 fgets 或 getline 读取消息直到换行符.
我正在使用 WebSockets。我创建了一个小型测试客户端,它将消息拆分,然后逐块发送。例如这样的消息:
PROTOCOL HTTP ACTION UPDATE
可以发送为
PROTOC
然后作为一个块
OL HTT
作为另一个而不是在一个块中发送完整的消息作为 PROTOCOL HTTP ACTION UPDATE
这也是一种可能性。
所以我接收消息的方式必须反映这一点。目前,我不确定如何使用 recv
当一条消息被分成多个部分并发送时。
这就是我正在尝试的方法,但我不确定这是否是正确的方法。我应该在接收时始终将缓冲区的大小保持为 200 吗?我应该什么时候退出循环?
void recv_all(){
char rec_buffer[200]
while(1) {
ssize_t bytes_rec = recv(socket_fd, rec_buffer, sizeof(rec_buffer),0);
}
}
您可以使用调用 read()
的返回值,然后使用 strcat()
将消息的各个部分粘合在一起。
根据 OP,消息以 \r\n
结尾,这是一个如何将消息作为多个数据包读取的示例。
char *message = malloc( MAX_MSG_LEN +1 );
if( ! message )
{
perror( "malloc failed" );
exit( EXIT_FAILURE );
}
// implied else, malloc successful
recv_buf[0] = '[=10=]';
size_t msgLen = 0;
int done = 0;
while( msgLen < MAX_MSG_LEN && !done)
{
ssize_t byteCount = read( socket_fd, message, MAX_MSG_LEN );
if( ! byteCount )
{
// handle error of sender closing the socket
}
else if( byteCount < 0 )
{
// handle I/O error
}
else
{
if( msgLen+byteCount > sizeof( recv_buf ) )
{
// handle error of message too long
}
else
{
message[ byteCount ] = '[=10=]';
strcat( recv_buf, message );
msgLen += byteCount;
if( memcmp( recv_buf[msgLen-2], "\r\n", 2 ) == 0 )
{
done = 1;
}
}
}
}
free( message );
注意:我没有运行上面的例子,所以可能需要做一些调试。
(stream) 套接字处理字节流,而不是消息。因此,它们提供了一种在端点之间获取字节流的方法,仅此而已。如果您想要某种 'messages',您需要处理字节流以找到消息边界并自行将其分解为消息。
执行此操作的通常方法是使用缓冲区,例如 C FILE 对象或 C++ streambuf。您安排字节从套接字读取到缓冲区,然后检查缓冲区中是否有完整的消息,通常是通过查找消息 terminator/boundary 标记(例如 \r\n 或只是 \ n).如果存在,则(仅)从缓冲区中删除消息。
在 C 语言中使用 POSIX 很容易做到——您可以使用 fdopen
打开一个带有套接字描述符的文件,然后使用 fgets 或 getline 读取消息直到换行符.