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

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • pytest指定用例_ppt怎么设置自定义放映顺序

    pytest指定用例_ppt怎么设置自定义放映顺序前言测试用例在设计的时候,我们一般要求不要有先后顺序,用例是可以打乱了执行的,这样才能达到测试的效果.有些同学在写用例的时候,用例写了先后顺序,有先后顺序后,后面还会有新的问题(如:上个用例返回

  • pycharm如何缩进多行代码_pycharm如何运行选中代码

    pycharm如何缩进多行代码_pycharm如何运行选中代码方法一:在代码界面,点击鼠标右键,然后按住鼠标左键下拉选择就行了方法二:直接按下快捷键,alt+shift+insert,然后长按鼠标左键下拉即可进入多行编辑模式。…

    2022年10月24日
  • SVN服务器安装 – Windows系统

    SVN服务器安装 – Windows系统Windows系统下SVN服务器搭建及遇到相关问题和处理方法记录

    2022年10月18日
  • MASQUERADE

    MASQUERADELinux两张网卡:eth0和eth1sudoiptables-tnat-APOSTROUTING-oeth0-jMASQUERADEMASQUERADE(IP地址伪装)sudoiptables-tnat-APOSTROUTING-s10.0.0.0/24-oeno1-jMASQUERADE以下防…

  • 文科生也能学会的Excel VBA 宏编程入门

    文科生也能学会的Excel VBA 宏编程入门文章目录VBA宏编程简介准备工作打开宏功能打开“开发工具”选项卡VBA编程示例任务介绍文件宏全局宏VBA宏编程简介VBA编程是Office系列软件自带的编程功能,也就是说不只是Excel,Word和PPT也能进行VBA编程。而“宏”可以理解为一组自动化程序,执行一个宏就能执行其对应的一系列操作。创建宏主要有两种方法,一种是录制宏,也就是将人的一些操作录下来,需要的时候执行宏就可以自动重复这些操…

  • 完全卸载flash浏览器插件_浏览器内置flash卸载

    完全卸载flash浏览器插件_浏览器内置flash卸载前天晚上不知道点到了什么东西,弹出来个窗口说浏览器的Flash插件需要升级,当时也没多想就确定了,结果发现QQ2009一开就崩溃,囧……找了半天发现问题出在升级的这个Flash插件上面,于是在控制面板中卸载掉,重新安装——一开QQ继续崩溃,继续囧……再查,发现在控制面板中卸载Flash插件之后,在C:\Windows\System32\Macromed\Flash\依旧存在两个文…

    2022年10月15日

发表回复

您的电子邮箱地址不会被公开。

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