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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 机器学习中【回归算法】详解

    机器学习中【回归算法】详解关注微信公众号【Microstrong】,我写过四年Android代码,了解前端、熟悉后台,现在研究方向是机器学习、深度学习!一起来学习,一起来进步,一起来交流吧!本文同步更新在我的微信公众号里,地址:https://mp.weixin.qq.com/s?__biz=MzI5NDMzMjY1MA==&amp;mid=2247483935&amp;idx=1&amp;sn=5e1c55c76…

    2022年8月21日
    3
  • centos7系统更新命令_centos 更新

    centos7系统更新命令_centos 更新1.查看网络IP ifconfig2.下载命令 wget+网址3.安装 yum-y install + 目标4.删除文件 sudo rm 文件所在目录/目标强制删除文件 rm -f删除目录 rm -rf5.复制一个文件到另一个文件夹sudo cp /文件夹/文件 /另一个文件夹6.对一些文件进行读写sudo vim 文件名7….

    2022年8月18日
    7
  • vsftp简介[通俗易懂]

    vsftp简介[通俗易懂]一、简介FTP(文件传输协议)全称是:VerySecureFTPServer。Vsftpd是linux类操作系统上运行的ftp服务器软件。vsftp提供三种登陆方式:1.匿名登录2.本地用户登录3.虚拟用户登录vsftpd的特点:1.较高的安全性需求2.带宽的限制3.创建支持虚拟用户4.支持IPV65.中等偏上的性能6.可分…

    2022年9月24日
    0
  • python深度学习库系列教程——python调用opencv库教程

    python深度学习库系列教程——python调用opencv库教程全栈工程师开发手册(作者:栾鹏)python教程全解OpenCV安装pipinstall–upgradesetuptoolspipinstallnumpyMatplotlibpipinstallopencv-pythonOpenCV的结构和Python一样,当前的OpenCV也有两个大版本,OpenCV2和OpenCV3。相比OpenCV2,OpenCV3提供了

    2022年9月26日
    0
  • DAO层,Service层,Controller层、View层

    DAO层,Service层,Controller层、View层DAO 层 DAO 层主要是做数据持久层的工作 负责与数据库进行联络的一些任务都封装在此 DAO 层的设计首先是设计 DAO 的接口 然后在 Spring 的配置文件中定义此接口的实现类 然后就可在模块中调用此接口来进行数据业务的处理 而不用关心此接口的具体实现类是哪个类 显得结构非常清晰 DAO 层的数据源配置 以及有关数据库连接的参数都在 Spring 的配置文件中进行配置 nbsp nbsp nbsp nbsp Service 层 Service 层主要负责业务模块的逻辑应用设计 同样是首先设计接口 再设计其实现的类 接着再 Spring 的配置文件中配

    2025年6月9日
    0
  • python趣味编程100例pdf(python简单实例)

    1#题目:一球从100米高度自由落下,每次落地后反跳回原高度的一半;再落下,求它在第10次落地时,共经过多少米?第10次反弹多高?代码:23h=04li=[]5foriinrange(1,11):6s=100/(2**(i-1))7li.append(s)89forxinli:10h+=x11print(li)12print(…

    2022年4月17日
    220

发表回复

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

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