【问题标题】:sending formatted messages across TCP connection通过 TCP 连接发送格式化消息
【发布时间】:2009-12-06 03:55:28
【问题描述】:

我有一个现有的 C 程序,它使用以下命令将许多消息打印到标准错误:

fprintf(stderr, ...

我想修改这个程序,以便这些消息也可以通过 Internet 上的 TCP 连接发送出去。 (我已经将其创建为 SOCK_STREAM 套接字。)将消息格式化为 fprintf 格式然后通过 Internet 发送出去的最佳方式是什么?

当然,在我可以发送消息之前,我首先需要知道它有多长,所以我可以先将长度发送给客户端,这样客户端就会知道要读取多少字节......

任何想法都将不胜感激!

【问题讨论】:

    标签: c sockets tcp printf


    【解决方案1】:

    连接套接字后,您可以在套接字文件描述符上使用fdopen() 将其作为流打开。这会给你一个FILE *,你可以将它传递给fprintf(),而不是stderr

    【讨论】:

    • 谢谢,但我想到了,据我所知,为了让客户知道每条消息要读多少个再见,我首先需要发送消息提前。我不认为仅仅通过 FILE * 代替 stderr 就可以做到这一点......
    • 好吧,如果您的所有消息都以\n 结尾,那么客户端可以一直阅读,直到看到一个。
    【解决方案2】:

    我建议你将输出调用包装在一个可变参数函数中(它是 printf 系列函数的工作方式),然后从那里做所有事情。例如,它可能看起来像:

    int multi_log(FILE * stream, int fd, const char * fmt, ...) {
       char buff[BUFF_MAX] = {0};
       int len = 0;
       va_list args;
       va_start (args, fmt);
       len = vsnprintf (buff, BUFF_MAX, fmt, args);
       va_end (args);
    
       fputs (buff, stream);
       write (fd, buff, len); 
    }
    

    这样您就可以根据需要添加和/或删除功能。

    注意使用vsnprintf返回的尺寸,请仔细阅读手册页

    【讨论】:

      【解决方案3】:

      我认为您需要查看 sprintf 或(更好)需要您提供显式输出缓冲区大小的变体。

      【讨论】:

        【解决方案4】:

        你让它变得比它需要的更难。如果您正在发送二进制数据,并且客户端需要识别消息边界,那么是的,您可能希望首先发送消息长度,或者使用某种“框架”来描绘消息边界。但在这种情况下,你不需要那个。您可以使用上述建议的方法将消息文本写入套接字。

        在另一端,对等方可以坐在一个循环中阅读文本,直到套接字关闭。如果您希望阅读器逐行处理文本,您可以用换行符标记每行的结尾。然后,读者可以扫描接收到的文本以查找那些换行符。

        唯一可能比较棘手的是,因为 TCP 是面向字节而不是面向消息的,所以阅读器不会总是以与发送者发送的相同大小的块获得文本。 (通常你会,但不能保证。)所以你的读者需要能够处理从套接字读取的单次读取可能会成为一行的一部分,或者可能是多行组合在一起的情况。这不是什么大问题,只要您编写代码时考虑到它可能发生的可能性。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-03-31
          • 1970-01-01
          • 1970-01-01
          • 2016-05-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多