1
votes

The following code is a programming sample for using UDP sockets.

There are 3 .c source files (Client_UDP.c, Server_UDP.c, and Message_UDP.c), and 1 .h header file (Prototype.h).

I want the Server and Client to communicate with each other only through the functions in Message_UDP.

The course of events seems to be like this:

  1. The Client sends a first packet/message to the Server.
  2. The Server receives the packet from the Client.
  3. The Server tries to send a response package, but shows an error: "Error in sendto(): Address family not supported by protocol".

Does anyone know why? How can I solve this?

Client_UDP.c

#include <stdio.h>      
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "Prototype.h"

int main(int argc, char * argv[]) {

    int fd_socket;

    struct sockaddr_in server;      
    socklen_t length_server = sizeof (server);

    fd_socket = socket(AF_INET, SOCK_DGRAM, 0);
    Error_A(fd_socket, "Error in socket()");

    server.sin_port = htons(8888);
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = inet_addr("127.0.0.1");

    // send packet to server
    function_SEND(fd_socket, server, length_server, "CLIENT");

    // receive packet from server
    function_RECEIVE(fd_socket, server, length_server, "CLIENT");

    close(fd_socket);
    return EXIT_SUCCESS;
}

Server_UDP.c

#include <stdio.h>      
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "Prototype.h"

int main(int argc, char * argv[]) {

    int fd_socket;
    int rv; // return value

    struct sockaddr_in server;
    struct sockaddr_in client;

    socklen_t length_server = sizeof (server);
    socklen_t length_client = sizeof (client);

    fd_socket = socket(AF_INET, SOCK_DGRAM, 0);
    Error_A(fd_socket, "Errore in socket()");

    server.sin_port = htons(8888);
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;

    rv = bind(fd_socket, (struct sockaddr *) &server, length_server);
    Error_A(rv, "Error in bind()");

    // receive packet from client
    function_RECEIVE(fd_socket, client, length_client, "SERVER");

    // send packet to client
    function_SEND(fd_socket, client, length_client, "SERVER");

    close(fd_socket);
    return EXIT_SUCCESS;
}

Message_UDP.c

#include <stdio.h>      
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "Prototype.h"

void Error_A(int return_value, char *error_message) {

    if (return_value < 0) {
        perror(error_message);
        exit(EXIT_FAILURE);
    }
}

void function_SEND(int fd_socket, struct sockaddr_in host, int length_host, char *sender) {

    int rv; // return value
    char packet[100] = "PACKET";

    // send packet
    rv = sendto(fd_socket, packet, 100, 0, (struct sockaddr *) &host, length_host);
    Error_A(rv, "Error in sendto()");
    printf("<%s> -- package sent: <%s> \n", sender, packet);
}

void function_RECEIVE(int fd_socket, struct sockaddr_in host, int length_host, char* receiver) {

    int rv; // return value
    char packet[100] = "";

    // receive packet
    rv = recvfrom(fd_socket, packet, 100, 0, (struct sockaddr *) &host, &length_host);
    Error_A(rv, "Errore in recvfrom()");
    printf("<%s> -- packet received: <%s> \n", receiver, packet);
}

Prototype.h

void Error_A(int return_value, char *error_message);

void function_SEND(int fd_socket, struct sockaddr_in host, int length_host, char *sender);

void function_RECEIVE(int fd_socket, struct sockaddr_in host, int length_host, char* receiver);

This is the client output:

CLIENT -- package sent: PACKET

This is the server output:

SERVER -- package received: PACKET

Error in sendto(): Address family not supported by protocol

2
Unrelated to your problem, but you do know that the port number should be in network byte order? I.e. you need to use e.g. server.sin_port = htons(8888);Some programmer dude
Much more related to your problem, don't forget that arguments to functions in C are passed by value. That means the arguments in a function are copies of the original values passed in. Modifying a copy does not modify the original. Think a little about why you need to pass a pointer to the socket address structure in the call to recvfrom, and do some research about emulating pass by reference in C.Some programmer dude
no sorry...i correct it nowLeonardo
Do you means to create a pointer to structure like this 'struct sockaddr_in *client' and then modify the function 'function_RECEIVE()' to pass it?Leonardo
No, client can still be a structure object like now, but you should modify your function_RECEIVE to expect a pointer, and pass it like you pass the structure to recvfrom.Some programmer dude

2 Answers

0
votes

I may be missing something obvious. Here is something I noted. In your Server_UDP.c, there is no initializion for the client. I see the declaration struct sockaddr_in client;, but there is no assignment. Here, I would assume the client would be assigned the same port number and the loop back IP address, like the following

client.sin_port = 8888;
client.sin_family = AF_INET;
client.sin_addr.s_addr = inet_addr("127.0.0.1");

This could be why the send is failing in the server

0
votes

I add this structure in the Prototype.h:

struct Host {
    struct sockaddr_in host;
    socklen_t length_host;
} host_return;

void Error_A(int return_value, char *error_message);

void function_SEND(int fd_socket, struct sockaddr_in host, int length_host, char *sender);

struct Host function_RECEIVE(int fd_socket, struct sockaddr_in host, int length_host, char* receiver);

Changing the function_RECEIVE() in Message_UDP.c with this:

struct Host function_RECEIVE(int fd_socket, struct sockaddr_in host, int length_host, char* receiver) {

    int rv; // return value
    char packet[100] = "";

    // receive packet
    rv = recvfrom(fd_socket, packet, 100, 0, (struct sockaddr *) &host, &length_host);
    Error_A(rv, "Errore in recvfrom()");
    printf("%s -- packet received: %s \n", receiver, packet);

    host_return.host = host;
    host_return.length_host = length_host;

    return host_return;
}

and the code in Server_UDP.c put this:

// receive packet from client
host_return = function_RECEIVE(fd_socket, client, length_client, "SERVER");
    
// send packet to client
function_SEND(fd_socket, host_return.host, host_return.length_host,"SERVER");

instead of

// receive packet from client
function_RECEIVE(fd_socket, client, length_client, "SERVER");

// send packet to client
function_SEND(fd_socket, client, length_client, "SERVER");

it seems to work because the output is (but i hope i don't have had just luck):

CLIENT -- packet sent: PACKET

CLIENT -- packet received: PACKET

server:

SERVER -- packet received: PACKET

SERVER -- packet sent: PACKET