cserveripv6winsock2recvfrom

IPv6 Server in c - recvfrom failed


i have written a small c-program for an IPv6 server with winsock2.h When I run the program in Visual Studio, I get the following message all the time: recvfrom failed

I just can't find the error in the recvfrom function. Maybe someone can see why my program does not work at this point, thanks! :-)

Best regards, Ken

#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;
    socklen_t client_len;
    char buf[1024];
    char clientIP[256];

    WSADATA data;
    WORD version = MAKEWORD(2, 2);
    if (WSAStartup(version, &data) == SOCKET_ERROR) {

        printf("WSASStartup failed\n");
        WSACleanup();
        exit(EXIT_FAILURE);
    }

    server_socket = socket(AF_INET6, SOCK_DGRAM, 0);
    if (server_socket == -1) {

        printf("creating socket failed\n");
        WSACleanup();
        exit(EXIT_FAILURE);
    }
    else {

        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, (const struct sockaddr*) & server_addr,
        sizeof(server_addr)) == -1) {

        printf("bind socket failed\n");
        WSACleanup();
        exit(EXIT_FAILURE);
    }
    else {

        printf("bind socket successful\n");
    }

    while (1) {

        memset(&client_addr, 0, sizeof(client_addr));
        memset(buf, 0, sizeof(buf));

        if (recvfrom(server_socket, (char*)buf, 1024, 0,
            (struct sockaddr*) & client_addr,
            sizeof(client_addr)) == -1) {

            printf("recvfrom failed\n");
            WSACleanup();
            exit(EXIT_FAILURE);
        }
        else {

            printf("recvfrom successful");
        }

        printf("%s\n", buf);
        printf("IP: %s\n", inet_ntop(AF_INET6, &client_addr.sin6_addr,
            clientIP, 256));
    }

    closesocket(server_socket);

    WSACleanup();

    return 0;
}

Solution

  • You are misusing recvfrom(). The fromlen parameter expects to receive an int* pointer that points to an int, which on input specifies the byte size of the sockaddr buffer being passed in the from parameter, and on output receives the byte size of the sockaddr written to the from buffer.

    There are also some other minor bugs in your code:

    Try this instead:

    #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;
    }