【问题标题】:Concatenating char buffer into a string将字符缓冲区连接成字符串
【发布时间】:2020-05-07 21:56:56
【问题描述】:

在接下来的sn-p中,我接收数据,直到我完全接收到来自socket客户端的所有数据。我继续将数据存储在大小为 300 的 char 缓冲区中。

ssize_t b;
char buffer[300]
while((b = recv(socket_fd,buffer,sizeof(buffer))) > 0) {
   // keep on receiving the data

}

但问题在于每次迭代时,缓冲区都会重新填充,旧值会丢失。如何将缓冲区值连接成一个,以便在循环结束时将消息作为一个完整的字符串?

【问题讨论】:

  • 创建一个单独的数组并将每个批次复制到该数组的末尾。
  • strncat
  • @johnelemans 你能举个例子吗?
  • @FiddlingBits 你能举个 c 的例子吗?
  • 你对数据做了什么?最终,您将不得不处理它,无论您的情况如何。你不能简单地永远保持接收和连接。您知道您可以接收的最大数据量吗?如果是这样,只需将缓冲区设置为该大小即可。如果不是,则取决于您使用的协议,以了解何时最好处理和丢弃与继续接收。

标签: c arrays memory-management char c-strings


【解决方案1】:

您可以执行以下操作。我假设缓冲区不包含字符串。

ssize_t b;
char buffer[300]
size_t n = 1;
char *s = calloc( 1, sizeof( char ) );

while((b = recv(socket_fd,buffer,sizeof(buffer))) > 0) {

    char *tmp = realloc( s, b + n );

    if ( !tmp )
    {
        // report an error
        break;
    }

    s = tmp;
    memcpy( s + n - 1, buffer, b );
    n += b;
    s[n - 1] = '\0';  
}

【讨论】:

  • 你能解释一下你到底做了什么吗?
  • @Amanda 您正在动态地重新分配数组 s 并从缓冲区中附加一个新的数据部分。
  • 我认为您误解了要求并且可能使解决方案过于复杂?
  • @Clifford 我认为她需要一个读取数据数组或缓冲区中的一个单独数组,其中将存储读取字符串以供进一步处理。所以这是唯一正确的方法。
  • “只有正确的方法”是一个大胆的主张,用特定于您的解决方案的关键字标记问题是一种可疑的做法;-)
【解决方案2】:

不是将buffer 传递给recv(),而是传递buffer 的下一个元素的地址 并累加一个索引,调整recv() 的大小参数以考虑已经写入的数据:

char buffer[300] ;
ssize_t buffer_index = 0 ;
ssize_t chunk = 0 ;

do 
{
   chunk = recv( socket_fd, 
                 &buffer[buffer_index], 
                 sizeof(buffer) - buffer_index - 1 ) ;

   if( chunk > 0 )
   {
       buffer_index += chunk ;
       buffer[buffer_index] = '\0' ;
   }

} while( buffer_index < sizeof(buffer) - 1 && 
         chunk > 0 ) ;


如果您需要在 \n 等分隔符处终止而不是简单地填充缓冲区或超时,那么您将需要一次读取和检查一个字符:

char buffer[300] ;
ssize_t buffer_index = 0 ;
ssize_t status = 0 ;

do 
{
   status = recv( socket_fd, 
                  &buffer[buffer_index], 
                  1 ) ;

   if( status > 0 )
   {
       buffer_index++ ;
       buffer[buffer_index] = '\0' ;
   }

} while( ch != '\n' && 
         buffer_index < sizeof(buffer) - 1 && 
         status > 0 ) ;

更完整的套接字readline() 函数示例可以在http://man7.org/tlpi/code/online/dist/sockets/read_line.c.html 中找到。

【讨论】:

  • 有没有办法检测到消息结束并退出循环?消息的结尾将被标记为\r\n
  • 由于某种原因这不起作用..只是错过了一些数据并连接了错误的结束
  • &gt; 0 ) 在这里没有意义——如果第一个循环中的recv 返回100,例如第二次返回-1,则需要立即退出。需要另一个 size_t 变量。
  • @KamilCuk 你能建议怎么做吗?
  • @KamilCuk 好点,需要一些返工。但无论如何,阿曼达的评论改变了这个问题。正在努力。
猜你喜欢
  • 2010-09-14
  • 2010-11-25
  • 1970-01-01
  • 2018-08-16
  • 2021-12-10
  • 1970-01-01
  • 1970-01-01
  • 2017-12-02
  • 2013-07-10
相关资源
最近更新 更多