Socket tips: UDP Echo service - Client code

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <time.h>

#define BUFFER_LENGTH 1024

void ExitWithMessage(const int errorCode, const char * errorMessage)
{
    fprintf(stderr, "\n\nError Msg  : %s\n", errorMessage);
    fprintf(stderr, "Error Code : 0x%X\n", errorCode);
    fprintf(stderr, "Location   : %s: %d\n\n", __FILE__, __LINE__);

    exit(errorCode);
}

void PrintIPv4(unsigned long ipvalue, FILE * stream)
{
    uint8_t a;
    uint8_t b;
    uint8_t c;
    uint8_t d;

    a = ipvalue >> 24;

    ipvalue -= a * 0x01000000;
    b = ipvalue >> 16;

    ipvalue -= b * 0x00010000;
    c = ipvalue >> 8;

    ipvalue -= c * 0100000100;
    d = ipvalue;

    fprintf(stream, "%d.%d.%d.%d", d, c, b, a);
}

void PrintSocketAddress(const struct sockaddr * address, FILE * stream)
{
    struct in_addr ip4addr;
    in_port_t port;

    struct sockaddr_in * ipv4Address;

    if(address == NULL || stream == NULL)
    {
        return;
    }

    //printf("sa_family: %d\n", address->sa_family);

    switch(address->sa_family)
    {
        case AF_INET:

            fputs("[IPv4] ", stream);

            ipv4Address = (struct sockaddr_in *)address;
            ip4addr = ipv4Address->sin_addr;

            port = ntohs(ipv4Address->sin_port);

            //fprintf(stream, "ip4addr.s_addr: %X\n", ip4addr.s_addr);
            PrintIPv4(ip4addr.s_addr, stream);
            fprintf(stream, " : %d", port);

            break;
        case AF_INET6:

            fputs("[IPv6] ", stream);

            break;
        default:
            fputs("[unknown type]", stream);
            return;
    }
}

int main(int argc, char * argv[])
{
    char * server;
    char * serverPort;
    char * echoString;
    size_t echoStringLength;

    struct addrinfo addrCriteria;
    struct addrinfo *serverAddr;
    int socketHandle;
    int returnValue;
    ssize_t receivedBytesCount;
    ssize_t sendBytesCount;
    struct sockaddr_storage responseAddr;
    socklen_t responseAddrLen = sizeof(struct sockaddr);
    char buffer[BUFFER_LENGTH + 1];
	
	int broadcastPermission = 1;

    if(argc < 3 || argc > 4)
    {
        ExitWithMessage(1, "Parameters: <Server_IPv4> <Server_Port> <Message>");
    }

    server = argv[1];
    serverPort = argv[2];
    echoString = argv[3];
    echoStringLength = strlen(echoString);

    if(echoStringLength >= BUFFER_LENGTH)
    {
        ExitWithMessage(2, "Message is too long.");
    }

    memset(&addrCriteria, 0, sizeof(struct addrinfo));

    addrCriteria.ai_family = AF_UNSPEC; // Any address family
    addrCriteria.ai_flags = AI_PASSIVE; // Accept on any address/port
    addrCriteria.ai_socktype = SOCK_DGRAM; // only datagram socket
    addrCriteria.ai_protocol = IPPROTO_UDP; // only UDP socket

    returnValue = getaddrinfo(server, serverPort, &addrCriteria, &serverAddr);
    if(returnValue != 0)
    {
        fprintf(stderr, "getaddrinfo() failed.\n");
        ExitWithMessage(returnValue, gai_strerror(returnValue));
    }

    // Create a datagram/UDP socket
    socketHandle = socket(serverAddr->ai_family, serverAddr->ai_socktype, serverAddr->ai_protocol);
    if(socketHandle < 0)
    {
        fprintf(stderr, "socket() failed.\n");
        ExitWithMessage(socketHandle, gai_strerror(socketHandle));
    }
	
	// Set socket to be allowed broadcast
	
	returnValue = setsockopt(
		socketHandle, SOL_SOCKET, 
		SO_BROADCAST, 
		(void *) &broadcastPermission, 
		sizeof(broadcastPermission));
		
	if(returnValue != 0)
    {
        fprintf(stderr, "setsockopt() failed.\n");
        ExitWithMessage(returnValue, gai_strerror(returnValue));
    }

    sendBytesCount = sendto(socketHandle, echoString, echoStringLength, 0, serverAddr->ai_addr, serverAddr->ai_addrlen);
    if(sendBytesCount < 0)
    {
        fprintf(stderr, "sendto() failed.\n");
        ExitWithMessage(sendBytesCount, gai_strerror(sendBytesCount));
    }

    // Receive a response

    receivedBytesCount = recvfrom(
		socketHandle,
		buffer,
		BUFFER_LENGTH,
		0,
		(struct sockaddr *)&responseAddr,
		&responseAddrLen);

    if(receivedBytesCount < 0)
    {
        fprintf(stderr, "recvfrom() failed.\n");
        ExitWithMessage(receivedBytesCount, gai_strerror(receivedBytesCount));
    }

	fputs("Server address: ", stdout);
    PrintSocketAddress((struct sockaddr *)&responseAddr, stdout);

    buffer[receivedBytesCount] = '\0';
    printf("\nResponse: %s\n", buffer);

	freeaddrinfo(serverAddr);

    return 0;
}

版权声明:本文博主原创文章,博客,未经同意不得转载。

posted @ 2015-10-24 19:43  phlsheji  阅读(155)  评论(0编辑  收藏  举报