Socket tips: UDP Echo service – Server code

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/118827.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • linux网络攻击威胁分析以及linux安全技巧 学习笔记

    linux网络攻击威胁分析以及linux安全技巧 学习笔记

    2021年8月31日
  • Java使用OSS实现上传文件

    Java使用OSS实现上传文件

    2021年11月12日
  • JavaScript闭包

    JavaScript闭包闭包内部函数拥有比它的外部函数更长的生命周期!!!函数可以访问它被创建时所处的上下文环境!!!内部函数能访问外部函数的实际变量,而无需复制!实例:/**点击li标签时,调用其onclick事件,执行代码段function(){alert(i);}*此时,i在全局中的值为4*/window.onload=init;functioninit(){ var

    2022年6月29日
  • js什么是匿名函数_js函数返回值

    js什么是匿名函数_js函数返回值js匿名函数的代码如下:(function(){ // 这里忽略jQuery 所有实现 })();半年前初次接触jQuery 的时候,我也像其他人一样很兴奋地想看看源码是什么样的。然而,在看到源码的第一眼,我就迷糊了。为什么只有一个匿名函数又没看到运行(当然是运行了…… ),就能有jQuery 这么个函数库了?于是,我抱着疑问来到CSDN 。结果相信现在很多人都很清楚了(因为在

    2022年9月27日
  • 手机和电脑将XPS转换成PDF的免费方法

    手机和电脑将XPS转换成PDF的免费方法如何将XPS转成PDF?最近有小伙伴收到很多后缀为XPS的文件,不知道如何打开,更不懂怎么样使用,如果能转成常用的PDF格式就好了。打开XPS文件最简单的方法当然还是安装对应的阅读器,比如XPSViewer;除此之外其实很多PDF阅读器也是可以直接打开XPS文档的,比如极速PDF阅读器。用以上任意一种方式打开XPS文件后,利用PDF生成的其中方式之一,将文件进行打印并选择PDF虚拟打印机就能直接将XPS文件以PDF格式进行保存了。这种方式一般适用于电脑端,毕竟手机无法进行这种虚拟打印机的操作。但如

    2022年5月4日
  • 阿里云和腾讯云免费SSL证书 – 知识林[通俗易懂]

    阿里云和腾讯云免费SSL证书 – 知识林[通俗易懂]本文章来自【知识林】概述什么是SSL证书通俗的来讲SSL和TSL都是属于网络传输的安全协议,而SSL继承于TSL,且SSL是一种更为安全的加密协议。SSL和TSL的体现:TSL是通过浏览器以http://来访问,默认端口是80;SSL是通过浏览器以https://来访问,默认端口是443。 为什么要使用SSL SSL更加安全 在使用微信小程序开发时与后台数据交互必须使用https传输,即SSL协议 SSL如何获得 SSL证书在很多网站上都有出售,且价格都不便

    2022年9月8日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号