отправка отформатированных сообщений по TCP-соединению - PullRequest
1 голос
/ 06 декабря 2009

У меня есть программа на C, которая печатает несколько сообщений со стандартной ошибкой, используя:

fprintf(stderr, ...

Я хотел бы изменить эту программу, чтобы эти сообщения также отправлялись через TCP-соединение через Интернет. (Который я уже создал как сокет SOCK_STREAM.) Как лучше всего отформатировать сообщения, как они были бы с помощью fprintf, а затем отправить их через Интернет?

Конечно, прежде чем я смогу отправить сообщение, мне сначала нужно знать, как долго это будет, чтобы я мог сначала отправить длину клиенту, чтобы клиент знал, сколько байтов нужно прочитать ...

Любые идеи будут наиболее ценными!

Ответы [ 4 ]

3 голосов
/ 06 декабря 2009

После подключения сокета вы можете открыть его как поток, используя fdopen() в дескрипторе файла сокета. Это даст вам FILE *, который вы можете передать fprintf() вместо stderr.

1 голос
/ 06 декабря 2009

Я бы посоветовал вам обернуть выходные вызовы в функцию переменного аргумента (как работает семейство функций 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 голосов
/ 31 июля 2015

Ты делаешь это сложнее, чем нужно. Если вы отправляете двоичные данные, и клиенту необходимо распознать границы сообщения, то да, вы хотите сначала отправить длину сообщения или использовать какое-то «кадрирование» для определения границ сообщения. Но в этом случае вам это не нужно. Вы можете просто записать текст сообщения в сокет, используя такой подход, как предложенный выше.

С другой стороны, партнер может просто сидеть в цикле, читая текст, пока сокет не будет закрыт. Если вы хотите, чтобы читатель обрабатывал текст построчно, вы можете пометить конец каждой строки символом новой строки. Затем читатель может просто просмотреть полученный текст в поисках этих символов новой строки.

Единственное, что может быть хитрым, это то, что, поскольку TCP ориентирован на байты, а не на сообщения, читатель не всегда получит текст в виде фрагментов того же размера, что и отправитель. (Обычно так и будет, но это не гарантировано.) Таким образом, ваш читатель должен уметь обрабатывать случай, когда одно чтение из сокета может получить часть строки или, возможно, объединение нескольких строк. Это не большая проблема, если вы кодируете вероятность того, что это может произойти.

0 голосов
/ 06 декабря 2009

Я думаю, вам нужно взглянуть на sprintf или (лучше) вариант, который требует, чтобы вы указали явный размер буфера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...