如何使用小缓冲区将格式化字符串发送到套接字?

时间:2014-01-07 20:57:53

标签: c sockets printf

我正在尝试将一些xml数据写入C中的套接字。我可以使用以下命令将xml字符串打印到屏幕:

printf("<tag1>%d</tag1>"
       "<tag2>%s</tag2>"
       "<tag3>%s</tag3>"
       "<tag4>%d</tag4>",
       int1,
       str2,
       str3,
       int4);

我尝试将snprintf字符串写入缓冲区(char[]),然后将缓冲区的内容写入套接字,而不是打印到stdout。不幸的是,我想这里缓冲区在写str2str3期间可能已满,可能甚至不足以包含任何一个字符串。

使用snprintf可以很容易地检查我是否能够将所有数据写入缓冲区,但是在将缓冲区内容发送到套接字后我不能继续停止。

基本上:如果格式化的字符串超过64个字节,是否有功能允许我将"%d%s%s%d"的64个字节发送到套接字?

如果此功能不存在,我对您建议的解决方法感兴趣(如果有帮助,您可以假设%s字段由一个试图溢出缓冲区的邪恶机器人填充,无论尺寸)。

2 个答案:

答案 0 :(得分:4)

在Linux上至少使用GNU libc,您可以使用asprintf(3)(提供malloc - ed字符串)或dprintf(3)(打印到文件描述符中)。< / p>

您还可以(并且更便携地)fdopen(3)套接字文件描述符,然后fprintf(3) fflush(3) 。您可以使用setvbuf(3)配置缓冲。

fileno(3)也很有用......

BTW,snprintf(3)返回所需字节的数量。所以你可以编码

char tinybuf[100];
char* buf = tinybuf;
int nbytes= snprintf(tinybuf, sizeof(tinybuf), 
                     "<tag at='%d'>%s</tag>", num, string);
if (nbytes >= sizeof(tinybuf)) { // rarely happens
    char *buf = malloc(nbytes+1);
    if (!buf) { perror("malloc"); abort(); };
    snprintf(buf, nbytes+1, 
             "<tag at='%d'>%s</tag>", num, string);
};
int off=0;
while (nbytes>0) {
   int nbw=write(sock, buf+off, nbytes); 
   if (nbw>0) { off += nbw; nbytes -= nbw; };
   else if (nbw<0 && errno != EINTR) { perror("write"); abort(); };
};
if (buf != tinybuf) free(buf);

这会避免在malloc适合的常见情况下freetinybuf ...

答案 1 :(得分:3)

如何将fprintf与套接字描述符一起使用?

类似的东西:

int sockfd = socket(AF_INET, SOCK_STREAM, 0);
FILE *fd = fdopen(sockfd, "w")
fprintf(fd, "<tag1>%d</tag1>"
   "<tag2>%s</tag2>"
   "<tag3>%s</tag3>"
   "<tag4>%d</tag4>",
   int1,
   str2,
   str3,
   int4);
fflush(fd);