手写TCP/IP——第7节UDP协议的实现3——时间服务器的开发

🌈hello,你好鸭,我是Ethan,西安电子科技大学大三在读,很高兴你能来阅读。

✔️目前博客主要更新Java系列、项目案例、计算机必学四件套等。
🏃人生之义,在于追求,不在成败,勤通大道。加油呀!

🔥个人主页:Ethan Yankang
🔥推荐:史上最强八股文||一分钟看完我的几百篇博客

🔥温馨提示:划到文末发现专栏彩蛋   点击这里直接传送

🔥本篇概览:详细讲解了手写TCP/IP的第7节UDP协议的实现3——时间服务器的开发。🌈⭕🔥


【计算机领域一切迷惑的源头都是基本概念的模糊,算法除外】


🔥 手写底层系列

🔥 手写TCP/IP系列

【OSI与课程讲解】


🌈章节引出

前一篇章:

🌈章节速览

基于UDP协议,实现一个时间服务器应用,向请求方发送当前时间。


1.常用熟知端口

2.代码实现时间服务器

2.1xserver_datetime.h

#ifndef XSERVER_DATETIME_H
#define XSERVER_DATETIME_H

#include "xnet_tiny.h"

xnet_err_t xserver_datetime_create(uint16_t port);

#endif // XSERVER_DATETIME_H

2.2xserver_datetime.c

#include "xserver_datetime.h"
#include <string.h>
#include <time.h>

#define TIME_STR_SIZE       128         // 时间字符串存储长度

static xnet_err_t datetime_handler (xudp_t * udp, xipaddr_t * src_ip, uint16_t src_port, xnet_packet_t * packet) {
    xnet_packet_t * tx_packet;
    time_t rawtime;
    const struct tm * timeinfo;

    tx_packet = xnet_alloc_for_send(TIME_STR_SIZE);
    if (tx_packet == (xnet_packet_t *)0) {
        return XNET_ERR_MEM;
    }

    // 参见:http://www.cplusplus.com/reference/ctime/localtime/
    time (&rawtime);
    timeinfo = localtime (&rawtime);

    // strftime参见:http://www.cplusplus.com/reference/ctime/strftime/
    // Weekday, Month Day, Year Time-Zone
    strftime((char *)tx_packet->data, TIME_STR_SIZE, "%A, %B %d, %Y %T-%z", timeinfo);
    truncate_packet(tx_packet, (uint16_t)strlen((char *)tx_packet->data));

    return xudp_out(udp, src_ip, src_port, tx_packet);
}

xnet_err_t xserver_datetime_create(uint16_t port) {
    xnet_err_t err;

    xudp_t* udp = xudp_open(datetime_handler);
    if (udp == (xudp_t*)0) {
        return -1;
    }

    err = xudp_bind(udp, port);
    if (err < 0) {
        xudp_close(udp);
        return err;
    }
    return 0;
}

3.UDP的数据负载图示

最后的黄色的UDP数据负载就是实实在在的应用的数据负载了!


4.UDP输入处理


4.1UDP包头定义

typedef struct _xudp_hdr_t {
    uint16_t src_port, dest_port;   // 源端口 + 目标端口
    uint16_t total_len;	            // 整个数据包的长度
    uint16_t checksum;		        // 校验和
}xudp_hdr_t;

4.2UDP初始化

/**
 * UDP初始化
 */
void xudp_init(void) {
    memset(udp_socket, 0, sizeof(udp_socket));      // Free也是0,所以没什么问题
}

4.3UDP输入处理

/**
 * UDP输入处理
 * @param udp 待处理的UDP
 * @param src_ip 数据包来源
 * @param packet 数据包结构
 */
void xudp_in(xudp_t *udp, xipaddr_t *src_ip,xnet_packet_t * packet) {
    xudp_hdr_t * udp_hdr = (xudp_hdr_t *)packet->data;
    uint16_t pre_checksum;
    uint16_t src_port;

    if ((packet->size < sizeof(xudp_hdr_t)) || (packet->size < swap_order16(udp_hdr->total_len))) {
        return;
    }

    pre_checksum = udp_hdr->checksum;
    udp_hdr->checksum = 0;
    if (pre_checksum != 0) {
        uint16_t checksum = checksum_peso(src_ip, &netif_ipaddr, XNET_PROTOCOL_UDP,
                                          (uint16_t *) udp_hdr, swap_order16(udp_hdr->total_len));
        checksum = (checksum == 0) ? 0xFFFF : checksum;
        if (checksum != pre_checksum) {
            return;
        }
    }

    src_port = swap_order16(udp_hdr->src_port);
    remove_header(packet, sizeof(xudp_hdr_t));
    if (udp->handler) {
        udp->handler(udp, src_ip, src_port, packet);
    }
}


5.UDP输出处理

服务器软件直接将数据包传送到UDP协议,返回给客户端:


5.1UDP发送函数 

/**
 * 发送一个UDP数据包
 * @param udp udp结构
 * @param dest_ip 目标ip
 * @param dest_port 目标端口
 * @param packet 待发送的包
 * @return 发送结果
 */
int xudp_out(xudp_t* udp, xipaddr_t * dest_ip, uint16_t dest_port, xnet_packet_t * packet) {
    xudp_hdr_t* udp_hdr;
    uint16_t checksum;

    add_header(packet, sizeof(xudp_hdr_t));
    udp_hdr = (xudp_hdr_t*)packet->data;
    udp_hdr->src_port = swap_order16(udp->local_port);
    udp_hdr->dest_port = swap_order16(dest_port);
    udp_hdr->total_len = swap_order16(packet->size);
    udp_hdr->checksum = 0;
    checksum = checksum_peso(&netif_ipaddr, dest_ip, XNET_PROTOCOL_UDP, (uint16_t *) udp_hdr, packet->size);
    udp_hdr->checksum = (checksum == 0) ? 0xFFFF : checksum;
    return xip_out(XNET_PROTOCOL_UDP, dest_ip, packet);;
}

5.2发送的流程:

 



💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖

热门专栏推荐

🌈🌈计算机科学入门系列                     关注走一波💕💕

🌈🌈CSAPP深入理解计算机原理        关注走一波💕💕

🌈🌈微服务项目之黑马头条                 关注走一波💕💕

🌈🌈redis深度项目之黑马点评            关注走一波💕💕

🌈🌈JAVA面试八股文系列专栏           关注走一波💕💕

🌈🌈JAVA基础试题集精讲                  关注走一波💕💕   

🌈🌈代码随想录精讲200题                  关注走一波💕💕


总栏

🌈🌈JAVA基础要夯牢                         关注走一波💕💕  

🌈🌈​​​​​​JAVA后端技术栈                          关注走一波💕💕  

🌈🌈JAVA面试八股文​​​​​​                          关注走一波💕💕  

🌈🌈JAVA项目(含源码深度剖析)    关注走一波💕💕  

🌈🌈计算机四件套                               关注走一波💕💕  

🌈🌈数据结构与算法                           ​关注走一波💕💕  

🌈🌈必知必会工具集                           关注走一波💕💕

🌈🌈书籍网课笔记汇总                       关注走一波💕💕         



📣非常感谢你阅读到这里,如果这篇文章对你有帮助,希望能留下你的点赞👍 关注❤收藏✅ 评论💬,大佬三连必回哦!thanks!!!
📚愿大家都能学有所得,功不唐捐!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值