Wednesday, May 30, 2012

C: UDP Client / Server App Using Sockets

Sending/ Receiving data structure over TCP/IP

Client:


/* timecli.c */
/* Gets the current time from a UDP server */
/* Last modified: September 23, 2005 */
/* http://www.gomorgan89.com */
/* Link with library file wsock32.lib */

#include
#include
#include
#include
//#include

#include
#include
#include
#include

// Need to link with Ws2_32.lib
#pragma comment(lib, "ws2_32.lib")


#define SIZE 500

struct packet {
           int x;
           int y;
           char arr[10];
} __attribute__((packed));

static void decode_packet (struct packet *recv_data, int recv_len);
void usage(void);


int main(int argc, char **argv)
{
WSADATA w; /* Used to open Windows connection */
unsigned short port_number; /* The port number to use */
SOCKET sd; /* The socket descriptor */
int server_length; /* Length of server struct */
char send_buffer[SIZE] = "GET TIME\r\n";/* Data to send */
char receive_buffer[10];               /* Data to receive */
time_t current_time; /* Time received */
struct hostent *hp; /* Information about the server */
struct sockaddr_in server; /* Information about the server */
struct sockaddr_in client; /* Information about the client */
int a1, a2, a3, a4; /* Server address components in xxx.xxx.xxx.xxx form */
int b1, b2, b3, b4; /* Client address components in xxx.xxx.xxx.xxx form */
char host_name[256]; /* Host name of this computer */

int retSocket;

    void* received_data;
    int   received_data_len;


/* Make sure command line is correct */
if (argc != 3 && argc != 4)
{
usage();
}
if (sscanf(argv[1], "%d.%d.%d.%d", &a1, &a2, &a3, &a4) != 4)
{
usage();
}
if (sscanf(argv[2], "%u", &port_number) != 1)
{
usage();
}
if (argc == 4)
{
if (sscanf(argv[3], "%d.%d.%d.%d", &b1, &b2, &b3, &b4) != 4)
{
usage();
}
}

/* Open windows connection */
if (WSAStartup(0x0101, &w) != 0)
{
fprintf(stderr, "Could not open Windows connection.\n");
exit(0);
}

/* Open a datagram socket */
sd = socket(AF_INET, SOCK_DGRAM, 0);
if (sd == INVALID_SOCKET)
{
fprintf(stderr, "Could not create socket.\n");
WSACleanup();
exit(0);
}

/* Clear out server struct */
memset((void *)&server, '\0', sizeof(struct sockaddr_in));

/* Set family and port */
server.sin_family = AF_INET;
server.sin_port = htons(port_number);

/* Set server address */
server.sin_addr.S_un.S_un_b.s_b1 = (unsigned char)a1;
server.sin_addr.S_un.S_un_b.s_b2 = (unsigned char)a2;
server.sin_addr.S_un.S_un_b.s_b3 = (unsigned char)a3;
server.sin_addr.S_un.S_un_b.s_b4 = (unsigned char)a4;

/* Clear out client struct */
memset((void *)&client, '\0', sizeof(struct sockaddr_in));

/* Set family and port */
client.sin_family = AF_INET;
client.sin_port = htons(0);


   
if (argc == 3)
{
/* Get host name of this computer */
gethostname(host_name, sizeof(host_name));
hp = gethostbyname(host_name);

/* Check for NULL pointer */
if (hp == NULL)
{
fprintf(stderr, "Could not get host name.\n");
closesocket(sd);
WSACleanup();
exit(0);
}

/* Assign the address */
client.sin_addr.S_un.S_un_b.s_b1 = hp->h_addr_list[0][0];
client.sin_addr.S_un.S_un_b.s_b2 = hp->h_addr_list[0][1];
client.sin_addr.S_un.S_un_b.s_b3 = hp->h_addr_list[0][2];
client.sin_addr.S_un.S_un_b.s_b4 = hp->h_addr_list[0][3];
}
else
{
client.sin_addr.S_un.S_un_b.s_b1 = (unsigned char)b1;
client.sin_addr.S_un.S_un_b.s_b2 = (unsigned char)b2;
client.sin_addr.S_un.S_un_b.s_b3 = (unsigned char)b3;
client.sin_addr.S_un.S_un_b.s_b4 = (unsigned char)b4;
}

/* Bind local address to socket */
if (bind(sd, (struct sockaddr *)&client, sizeof(struct sockaddr_in)) == -1)
{
fprintf(stderr, "Cannot bind address to socket.\n");
closesocket(sd);
WSACleanup();
exit(0);
}

/* Print out client information */
printf("Client running on %u.%u.%u.%u\n", (unsigned char)client.sin_addr.S_un.S_un_b.s_b1,
 (unsigned char)client.sin_addr.S_un.S_un_b.s_b2,
 (unsigned char)client.sin_addr.S_un.S_un_b.s_b3,
 (unsigned char)client.sin_addr.S_un.S_un_b.s_b4);

/* Tranmsit data to get time */
server_length = sizeof(struct sockaddr_in);





    while (1){
       
        retSocket = sendto(sd, send_buffer, (int)strlen(send_buffer) + 1, 0, (struct sockaddr *)&server, server_length);
    if (retSocket == SOCKET_ERROR)
    {
    fprintf(stderr, "Error transmitting data.\n");
    closesocket(sd);
    WSACleanup();
    exit(0);
    }
       
   
    /* Receive time */
    struct packet p;
   
    received_data = &p;
    received_data_len = sizeof(p);
   
    //recv(sd, (void*) &a, sizeof(a), 0);
    retSocket = recvfrom(sd,  (void*)received_data, received_data_len, 0, (struct sockaddr *)&server, &server_length);
    //retSocket = recvfrom(sd, receive_buffer, (int)sizeof(receive_buffer) + 1, 0, (struct sockaddr *)&server, &server_length);
    if (retSocket == SOCKET_ERROR)
    {
    fprintf(stderr, "Error receiving data.\n");
    closesocket(sd);
    WSACleanup();
    exit(0);
    }
   
    decode_packet(received_data, received_data_len);
   
    /* Display received data */
    // printf("Received data: %d", ntoh(received_data->x));
   
    Sleep(1000); // this will make the program pause for 1000 milliseconds
    }
   
   
closesocket(sd);
WSACleanup();

return 0;
}

static void decode_packet (struct packet *recv_data, int recv_len)
{
    struct packet *recv_packet;
    char string[10];

    // check size
    if (recv_len < sizeof(struct packet)) {
        fprintf(stderr, "received too little!");
        return;
    }  
   
    // make pointer
    recv_packet = (struct packet *)recv_data;
   

    // fix byte order
    int x = ntohl(recv_packet->x);
    int y = ntohl(recv_packet->y);
    string[0] = recv_packet->arr;
   
    strcpy(string, recv_packet->arr);

    printf("Decoded: %d %d %s", x, y, string);
}

void usage(void)
{
fprintf(stderr, "Usage: timecli server_address port [client_address]\n");
exit(0);
}






Server



/* timeserv.c */
/* A simple UDP server that sends the current date and time to the client */
/* Last modified: September 20, 2005 */
/* http://www.gomorgan89.com */
/* Link with library file wsock32.lib */

#include
#include
#include
#include

#include
#include
#include

// Need to link with Ws2_32.lib
#pragma comment(lib, "ws2_32.lib")

#define BUFFER_SIZE 20

void usage(void);


int main(int argc, char **argv)
{
WSADATA w; /* Used to open windows connection */
unsigned short port_number; /* Port number to use */
int a1, a2, a3, a4; /* Components of address in xxx.xxx.xxx.xxx form */
int client_length; /* Length of client struct */
int bytes_received; /* Bytes received from client */
SOCKET sd; /* Socket descriptor of server */
struct sockaddr_in server; /* Information about the server */
struct sockaddr_in client; /* Information about the client */
char buffer[BUFFER_SIZE]; /* Where to store received data */
struct hostent *hp; /* Information about this computer */
char host_name[256]; /* Name of the server */
time_t current_time; /* Current time */
char send_buffer[10] = "HELLO\r\n"; /* Data to send */

    struct packet {
           int x;
           int y;
           char arr[10];
    } __attribute__((packed));
   
    void* send_data;
    int   send_data_len;

/* Interpret command line */
if (argc == 2)
{
/* Use local address */
if (sscanf(argv[1], "%u", &port_number) != 1)
{
usage();
}
}
else if (argc == 3)
{
/* Copy address */
if (sscanf(argv[1], "%d.%d.%d.%d", &a1, &a2, &a3, &a4) != 4)
{
usage();
}
if (sscanf(argv[2], "%u", &port_number) != 1)
{
usage();
}
}
else
{
usage();
}

/* Open windows connection */
if (WSAStartup(0x0101, &w) != 0)
{
fprintf(stderr, "Could not open Windows connection.\n");
exit(0);
}

/* Open a datagram socket */
sd = socket(AF_INET, SOCK_DGRAM, 0);
if (sd == INVALID_SOCKET)
{
fprintf(stderr, "Could not create socket.\n");
WSACleanup();
exit(0);
}

/* Clear out server struct */
memset((void *)&server, '\0', sizeof(struct sockaddr_in));

/* Set family and port */
server.sin_family = AF_INET;
server.sin_port = htons(port_number);

/* Set address automatically if desired */
if (argc == 2)
{
/* Get host name of this computer */
gethostname(host_name, sizeof(host_name));
hp = gethostbyname(host_name);

/* Check for NULL pointer */
if (hp == NULL)
{
fprintf(stderr, "Could not get host name.\n");
closesocket(sd);
WSACleanup();
exit(0);
}

/* Assign the address */
server.sin_addr.S_un.S_un_b.s_b1 = hp->h_addr_list[0][0];
server.sin_addr.S_un.S_un_b.s_b2 = hp->h_addr_list[0][1];
server.sin_addr.S_un.S_un_b.s_b3 = hp->h_addr_list[0][2];
server.sin_addr.S_un.S_un_b.s_b4 = hp->h_addr_list[0][3];
}
/* Otherwise assign it manually */
else
{
server.sin_addr.S_un.S_un_b.s_b1 = (unsigned char)a1;
server.sin_addr.S_un.S_un_b.s_b2 = (unsigned char)a2;
server.sin_addr.S_un.S_un_b.s_b3 = (unsigned char)a3;
server.sin_addr.S_un.S_un_b.s_b4 = (unsigned char)a4;
}

/* Bind address to socket */
if (bind(sd, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) == -1)
{
fprintf(stderr, "Could not bind name to socket.\n");
closesocket(sd);
WSACleanup();
exit(0);
}

/* Print out server information */
printf("Server running on %u.%u.%u.%u\n", (unsigned char)server.sin_addr.S_un.S_un_b.s_b1,
 (unsigned char)server.sin_addr.S_un.S_un_b.s_b2,
 (unsigned char)server.sin_addr.S_un.S_un_b.s_b3,
 (unsigned char)server.sin_addr.S_un.S_un_b.s_b4);
printf("Press CTRL + C to quit\n");






/* Loop and get data from clients */
while (1)
{

client_length = (int)sizeof(struct sockaddr_in);

/* Receive bytes from client */

bytes_received = recvfrom(sd, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&client, &client_length);
if (bytes_received < 0)
{
fprintf(stderr, "Could not receive datagram.\n");
closesocket(sd);
WSACleanup();
exit(0);
}



/* Check for time request */
if (strcmp(buffer, "GET TIME\r\n") == 0)
{
/* Build packet */
struct packet p;
p.x = htonl(17);
            p.y = htonl(2924);
            memset(p.arr, '0', sizeof(p.arr));
            strcpy(p.arr, "hello");
           
           
            send_data = &p;
            send_data_len = sizeof(p);

/* Send data back */
if (sendto(sd, (void*)send_data, send_data_len, 0, (struct sockaddr *)&client, client_length) != (int)sizeof(p))
{
fprintf(stderr, "Error sending datagram.\n");
closesocket(sd);
WSACleanup();
exit(0);
}
}
}
closesocket(sd);
WSACleanup();

return 0;
}

void usage(void)
{
fprintf(stderr, "timeserv [server_address] port\n");
exit(0);
}