Socket tips: UDP Echo service - Server 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 ReverseMessage(char buffer[], ssize_t receivedBytesCount);

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

void PrintTime(FILE * stream)
{
    time_t currentTime;
    struct tm * local_time;
    struct timeval tv;

    currentTime = time(0);
    local_time = localtime(¤tTime);
    gettimeofday(&tv);

    fprintf(stream, "%04d-%02d-%02d %02d:%02d:%02d.%03d",
            local_time->tm_year + 1900,
            local_time->tm_mon + 1,
            local_time->tm_mday,
            local_time->tm_hour,
            local_time->tm_min,
            local_time->tm_sec,
            tv.tv_usec / 1000);

}

int main(int argc, char * argv[])
{
    char * serverPortString;
    struct addrinfo addrCriteria;
    struct addrinfo *serverAddr;
    int socketHandle;
    int returnValue;

    struct sockaddr_storage clientAddr;
    socklen_t clientAddrLen = sizeof(struct sockaddr);
    char buffer[BUFFER_LENGTH];
    ssize_t receivedBytesCount;
    ssize_t sendBytesCount;

    if(argc != 2)
    {
        //ExitWithMessage(0xF001, "Need parameter: <Server_Port>");
        serverPortString = "2001";
    }
    else
    {
        // First argument: local port
        serverPortString = argv[1];
    }

    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(NULL, serverPortString, &addrCriteria, &serverAddr);
    if(returnValue != 0)
    {
        fprintf(stderr, "getaddrinfo() failed.\n");
        ExitWithMessage(returnValue, gai_strerror(returnValue));
    }

    // Create socket for incomming connections
    socketHandle = socket(serverAddr->ai_family, serverAddr->ai_socktype, serverAddr->ai_protocol);
    if(socketHandle < 0)
    {
        fprintf(stderr, "socket() failed.\n");
        ExitWithMessage(socketHandle, gai_strerror(socketHandle));
    }

    // Bind to local address
    returnValue = bind(socketHandle, serverAddr->ai_addr, serverAddr->ai_addrlen);
    if(returnValue < 0)
    {
        fprintf(stderr, "bind() failed.\n");
        ExitWithMessage(returnValue, gai_strerror(returnValue));
    }

    // Free address list allocated by getaddrinfo
    freeaddrinfo(serverAddr);

    printf("Starting the UDP Server ...\n");
    printf("Listinning at port %s\n\n", serverPortString);

    while(1)
    {
        receivedBytesCount = recvfrom(
			socketHandle,
			buffer,
			BUFFER_LENGTH,
			0,
			(struct sockaddr *)&clientAddr,
			&clientAddrLen);

        // printf("Received %d bytes.\n", receivedBytesCount);

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

        fputs("Handling client ", stdout);
        PrintSocketAddress((struct sockaddr *)&clientAddr, stdout);

        fputs(" at ", stdout);
        PrintTime(stdout);

        fputc('\n', stdout);

        buffer[receivedBytesCount] = '\0';

        fputs("Message: ", stdout);
        fputs(buffer, stdout);
        fputs("\n\n", stdout);

		ReverseMessage(buffer, receivedBytesCount);
        sendBytesCount = sendto(socketHandle, buffer, receivedBytesCount, 0, (struct sockaddr *)&clientAddr, sizeof(clientAddr));
        if(sendBytesCount < 0)
        {
            fprintf(stderr, "sendto() failed.\n");
            ExitWithMessage(sendBytesCount, gai_strerror(sendBytesCount));
        }
    }

    return 0;
}

void ReverseMessage(char buffer[], ssize_t receivedBytesCount)
{
	ssize_t i;
	ssize_t j;
	char temp;

	for(i = 0; i < receivedBytesCount / 2; i++)
	{
		j = receivedBytesCount - 1 - i;

		temp = buffer[i];
		buffer[i] = buffer[j];
		buffer[j] = temp;
	}
}

posted @ 2014-07-29 12:06  yxwkaifa  阅读(302)  评论(0编辑  收藏  举报