Слушатель UDP в C не выводит правильную шестнадцатеричную информацию
Я пытаюсь прослушать определенный порт (6053) и хочу напечатать все данные, поступающие через этот порт. Но я не могу заставить мою программу работать правильно, она выводит ошибочные данные / неверные данные, так как они не совпадают с данными, поступающими из проводной акулы. Если у кого-то есть какие-либо предложения или предложения относительно направления, которое я должен возглавлять, это будет высоко ценится!
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <WinSock2.h>
#include <winsock.h>
#include <string.h>
#include <sys/types.h>
#include <assert.h>
int main(void) {
sockaddr_in si_me, si_other;
int s;
assert((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) );//!= -1
int port = 6053;
int broadcast = 1;
setsockopt(s, SOL_SOCKET, SO_BROADCAST,
(const char * )&broadcast, sizeof broadcast);
memset(&si_me, 0, sizeof(si_me));
si_me.sin_family = AF_INET;
si_me.sin_port = htons(port);
si_me.sin_addr.s_addr = INADDR_ANY;
assert(::bind(s, (sockaddr *)&si_me, sizeof(sockaddr)) );//!= -1
while (1)
{
char buf[10000];
int slen = sizeof(sockaddr);
recvfrom(s, buf, sizeof(buf) - 1, 0, (sockaddr *)&si_other, &slen);
printf("recv: %x\n", buf);
}
}
2 ответа
Прежде всего, вы не проверяете результат возврата recvfrom
, Так что ваши buf
массив может содержать ошибочные данные / неверные данные в точности так, как вы это описали. Не могли бы вы проверить документацию MSDN, например (или любое другое руководство по recvfrom), поскольку оно содержит хорошую отправную точку: https://msdn.microsoft.com/en-us/library/windows/desktop/ms740120(v=vs.85).aspx
printf("recv: %x\n", buf);
надеется buf
быть int
, который он печатает в шестнадцатеричном формате. Но buf
это не int
; это char*
(после гниения). Так ты врешь printf
о типе buf
, вызывая неопределенное поведение. Одним из возможных выражений UB будет то, что напечатанное шестнадцатеричное значение является последними 32 битами адреса вашего буфера, который, безусловно, не будет иметь никакого отношения к полученным данным.
Если бы вы собрали с -Wall
ваш компилятор предупредил бы вас об этом.
Он также мог бы предупредить вас о том, что вы не используете возвращаемое значение recvfrom
, Поскольку передачи UDP могут включать байты NUL (и, следовательно, обычно не являются строками C, которые не могут содержать NUL), вам необходимо знать, сколько байтов вы получили. recvfrom
предоставляет эту информацию в качестве возвращаемого значения, которое также сообщит вам, произошла ошибка или нет. Нет другого способа узнать, сколько байтов было получено, поэтому использование возвращаемого значения фактически обязательно.
Поскольку пакет получен recvfrom
не завершается NUL, нет смысла резервировать байт для завершения NUL; это не будет использоваться. (Если бы вы точно знали, что пакеты являются строками и хотели, чтобы буфер заканчивался NUL, вам придется делать это самостоятельно, используя длину, возвращаемую recvfrom
, В этом случае вам нужно будет оставить место для байта.)