2009-12-06 66 views
1

我有一个现有的C程序,打印使用许多消息发送到标准误差:通过TCP连接发送的格式化消息

fprintf(stderr, ... 

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

当然,在发送消息之前,我首先需要知道它是多长时间,所以我可以首先将长度发送到客户端,以便客户端知道要读取多少字节...

任何想法将不胜感激!

回答

0

我认为你需要看sprintf或(更好)的变体,要求你提供一个明确的缓冲区大小。

3

连接套接字后,可以使用套接字文件描述符上的fdopen()作为流打开它。这会给你一个FILE *,你可以通过fprintf()来代替stderr

+0

谢谢,但我想到了这一点,并且据我所知,为了让客户知道每条消息有多少个字节读入,我首先需要提前发送消息的长度。我不认为通过传递FILE *代替stderr可以实现这一点...... – Charles 2009-12-06 04:29:38

+0

好吧,如果所有的消息都以'\ n'结束,那么客户端可以直到它看到一个消息。 – caf 2009-12-06 04:55:39

+0

...一旦你有'FILE *'使用'fdopen()',那么在读取端使用'fgets()',''fscanf()'等很容易。 – mark4o 2009-12-06 05:18:48

1

我建议你将输出调用包装在一个变量参数函数中(它的函数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返回的大小,读你的男人页仔细

0

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

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

唯一可能会棘手的是,因为TCP是面向字节的而不是面向消息的,所以读者不会总是得到与发送者发送的大小相同的文本块。 (通常你会,但不能保证。)所以你的阅读器需要能够处理从套接字读取一部分可能会成为一部分的一部分,或者可能结合多行的情况。这不是一个大问题,只要你为可能发生的可能性编码。