Вы неправильно используете recvfrom()
. Параметр fromlen
ожидает получения указателя int*
, который указывает на int
, который на входе указывает размер байта буфера sockaddr
, передаваемого в параметре from
, а на выходе получает размер байта sockaddr
, записанных в буфер from
.
В вашем коде есть и другие незначительные ошибки:
WSAStartup()
не возвращает SOCKET_ERROR
при ошибке возвращает действительный код ошибки.
вы игнорируете возвращаемое значение recvfrom()
, которое говорит вам, сколько байтов было фактически записано в ваш buf
. Вы предполагаете, что buf
всегда завершается нулем при передаче его в printf("%s")
, но это не гарантируется. Вы обнуляете buf
, чтобы инициализировать его нулевыми терминаторами, что хорошо, если recvfrom()
получает дейтаграмму, содержащую менее 1024 байтов. Но если он получит дейтаграмму с ровно 1024 байтами, тогда все ваши нулевые терминаторы будут перезаписаны, и для printf()
не останется ни одного терминатора (если recvfrom()
получит дейтаграмму с более чем 1024 байтами, произойдет сбой с ошибка WSAEMSGSIZE
, которая не является фатальной ошибкой, но вы рассматриваете ее так, как если бы она была). Вместо того чтобы вообще полагаться на нулевые терминаторы, вы можете передать возвращаемое значение от recvfrom()
до printf()
для размера буфера. Не нужно тратить накладные расходы на обнуление того, что recvfrom()
будет перезаписано.
Попробуйте вместо этого:
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#pragma comment(lib, "Ws2_32.lib")
int main(int argc, char* argv[]) {
SOCKET server_socket;
struct sockaddr_in6 server_addr, client_addr;
int client_len, num_recvd;
char buf[1024];
char clientIP[256];
WSADATA data;
WORD version = MAKEWORD(2, 2);
int errCode = WSAStartup(version, &data);
if (errCode != 0) {
printf("WSAStartup failed, error %d\n", errCode);
WSACleanup();
return EXIT_FAILURE;
}
server_socket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
if (server_socket == INVALID_SOCKET) {
errCode = WSAGetLastError();
printf("creating socket failed, error %d\n", errCode);
WSACleanup();
return EXIT_FAILURE;
}
printf("creating socket successful\n");
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin6_addr = in6addr_any;
server_addr.sin6_family = AF_INET6;
server_addr.sin6_port = htons(5001);
if (bind(server_socket, (struct sockaddr*) &server_addr, sizeof(server_addr)) == SOCKET_ERROR) {
errCode = WSAGetLastError();
printf("bind socket failed, error %d\n", errCode);
closesocket(server_socket);
WSACleanup();
return EXIT_FAILURE;
}
printf("bind socket successful\n");
while (1) {
client_len = sizeof(client_addr);
num_recvd = recvfrom(server_socket, buf, sizeof(buf), 0, (struct sockaddr*) &client_addr, &client_len);
if (num_recvd == SOCKET_ERROR) {
errCode = WSAGetLastError();
if (errCode != WSAEMSGSIZE) {
printf("recvfrom failed, error %d\n", errCode);
closesocket(server_socket);
WSACleanup();
return EXIT_FAILURE;
}
printf("recvfrom truncated a datagram larger than %u bytes!\n", sizeof(buf));
num_recvd = sizeof(buf);
}
else {
printf("recvfrom successful\n");
}
printf("%.*s\n", num_recvd, buf);
printf("IP: %s\n", inet_ntop(AF_INET6, &client_addr.sin6_addr, clientIP, 256));
}
closesocket(server_socket);
WSACleanup();
return 0;
}