网络、UDP(用户数据报)编程

本文详细介绍了网络协议模型,包括OSI模型和TCP/IP模型,重点剖析了应用层的常用协议如HTTP、HTTPS等,以及传输层的TCP和UDP的特性和用法。此外,还通过socket编程展示了UDP的基础发送与接收操作,涉及函数如socket(),sendto(),bind(),recvfrom()等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.网络协议模型:


    OSI协议模型


        应用层              实际发送的数据
        表示层              发送的数据是否加密
        会话层              是否建立会话连接   连接状态
        传输层              数据传输的方式(数据报、流式)
        网络层              数据的路由(如何从一个局域网到达另一个局域网)        IP地址
        数据链路层          局域网下如何通信  交换机  数据格式化  帧 校验
        物理层              物理介质的连接 100Mb/8   网线、   10GB光纤 光 转 电信号 猫  

无线网频率2.4G 5G

    TCP/IP协议模型   协议栈

        应用层              传输的数据       
        传输层              传输的方式     端口号  tcp/udp
        网络层              数据如何从一台主机到达另一 台主机 IP地址   RIP OSPF
        接口层          物理介质的连接      网卡、驱动   ip --->mac(固定的)

        ip地址会变,mac地址是唯一固定的。

DNS 域名解析    www.baidu.com   ------> 180.76.76.76

DHCP (动态主机配置协议)是一种网络协议,用于自动分配IP地址和其他网络配置参数给网络中的设备。

    应用层:
        HTTP    超文本传输协议
        HTTPS   
        FTP     文件传输协议
        TFTP    简单文本传输协议 短距离文件传输  虚拟机和主机之间   ARM板和pc端
        SMTP    邮件传输协议
        MQTT    
        TELNET  
        ..
    
    传输层:
        UDP     用户数据报协议
                特点:
                    1.实现机制简单
                    2.资源开销小
                    3.不安全不可靠

        TCP     传输控制协议
                特点:
                    1.实现机制复杂
                    2.资源开销大
                    3.安全可靠

    网络层:
        IPv4

        IP地址:唯一标识网络中一台主机的标号
        IP地址:网络位 + 主机位

 


        子网掩码:用来标识IP地址的网络位和主机位
                子网掩码是1的部分表示IP地址的网络位
                子网掩码是0的部分表示IP地址的主机位


        网段号:网络位不变,主机位全为0,表示网段号
        广播地址:网络位不变,主机位全为1,表示广播地址

        IP地址类型:
        A类
            1.0.0.0 - 126.255.255.255
            子网掩码:255.0.0.0
            管理超大规模网络
            10.0.0.0 - 10.255.255.255 

        B类
            128.0.0.0 - 191.255.255.255
            子网掩码:255.255.0.0 
            管理大中规模型网络
            172.16.0.0 - 172.31.255.255

        C类
            192.0.0.0 - 223.255.255.255
            子网掩码:255.255.255.0
            管理中小规模型网络 
            192.168.0.0 - 192.168.255.255

        D类
            224.0.0.0 - 239.0.0.0
            用于组播

        E类
            240.0.0.0 - 255.255.255.255 
            用于实验

ip + port  地址+端口 ===》  地址用来识别主机   

                                                端口用来识别应用程序

      port分为TCP port / UDP port  范围都是: 1-65535
          约定1000 以内的端口为系统使用。
            http 80   www.baidu.com
                3306  mysql
                telnet 21 
                ssh 22

网络字节序       网络设备默认工作在大端模式下

ip地址和端口号 需要进行大小端转换

能接触到的大端设备(网络设备,51单片机)

UDP编程

套接字本质就是文件描述符。

socket API

application interface

 C/S 模式  ==》服务器/客户端模型

    socket套接字编程:

   客户端     发端:socket -> sendto -> close 
   服务器      收端: socket -> bind -> recvfrom -> close 


    1.发端:


        socket   与open()相似,用来打开计算机上的网络设备


        int socket(int domain, int type, int protocol);


        功能:
            创建一个用来通信的文件描述符


        参数:
            domain:使用的协议族 AF_INET (IPv4协议族)


            type:套接字类型
                SOCK_STREAM:流式套接字
                SOCK_DGRAM:数据报套接字
                SOCK_RAW:原始套接字


            protocol:协议
                默认为0 


        返回值:
            成功返回文件描述符
            失败返回-1 

        sendto 


        ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                      const struct sockaddr *dest_addr, socklen_t addrlen);

        功能:
            利用套接字向指定地址发送数据信息 


        参数:
            sockfd:套接字文件描述符
            buf:发送数据空间首地址
            len:发送数据的长度
            flags:属性默认为0 
            dest_addr:目的地址信息存放的空间首地址
            addrlen:目的地址的长度
        
        struct sockaddr_in {
            sa_family_t    sin_family; /* address family: AF_INET */
            in_port_t      sin_port;   /* port in network byte order */
            struct in_addr sin_addr;   /* internet address */
        };

        /* Internet address. */
        struct in_addr {
            uint32_t       s_addr;     /* address in network byte order */
        };
                  
        返回值:
            成功返回实际发送字节数
            失败返回-1 

        inet_addr


        in_addr_t  inet_addr(const char *cp);
        功能:  
            将字符串IP地址转换为内存中的IP地址 

        htons


        uint16_t htons(uint16_t hostshort);


        功能:
            将本地字节序转换为网络的大端字节序
   

 close(sockfd) 关闭套接字

2.收端

        bind 


            int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
    功能:
        在套接字上绑定一个IP地址和端口号


    参数:
        sockfd:套接字文件描述符
        addr:绑定IP地址空间首地址
        addrlen:绑定IP地址的长度


    返回值:
        成功返回0 
        失败返回-1 

    recvfrom


    ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                        struct sockaddr *src_addr, socklen_t *addrlen);


    功能:
        从套接字中接收数据


    参数:
        sockfd:套接字文件描述符
        buf:存放数据空间首地址
        flags:属性 默认为0 
        src_addr:存放IP地址信息的空间首地址
        addrlen:存放接收到IP地址大小空间的首地址


    返回值:
        成功返回实际接收字节数
        失败返回-1 

UDP 基础的发送与接收的例程

        

 head.h

#ifndef _HEAD_H
#define _HEAD_H
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/wait.h>

#include<unistd.h>

#include<fcntl.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

#include<time.h>
#include<grp.h>

#include<sys/ipc.h>
#include<sys/msg.h>
#include<sys/shm.h>
#include<sys/sem.h>
#include<sys/socket.h>
#include<netinet/ip.h>
#include<arpa/inet.h>

#define RECV_ADDR "192.168.1.157"
#define RECV_PORT 50000
#endif
send.c
/*************************************************************************
	> File Name: send.c
	> Author: yas
	> Mail: rage_yas@hotmail.com
	> Created Time: 2024年03月06日 星期三 22时06分24秒
 ************************************************************************/

#include"head.h"
int main(void)
{
    int sockfd = 0;        //创建整型sockfd 用来保存socket(套件字)文件描述符 
    char tmpbuff[1024] = {0};     // 发送的数据
    ssize_t nsize = 0;            //发送数据的大小
    struct sockaddr_in recvaddr;   //创建sockaddr_in类型的结构体 recvaddr    用于保存 接收方 的地址信息

    sockfd = socket(AF_INET,SOCK_DGRAM,0);// AF_INET 表示IPv4 协议  SOCK_DGRAM 表示数据报套接字
    if(-1 == sockfd)
    {
        perror("fail to socket");
        return -1;
    }

    recvaddr.sin_family = AF_INET;   //设置接收方地址的地址族 为AF_INET (IPv4)
    recvaddr.sin_port  = htons(50000); //设置接收方的端口号为50000
    recvaddr.sin_addr.s_addr = inet_addr("192.168.1.157"); //设置接收方的IP地址为“192.168.1.157” 
        //inet_addr 将ip地址转换为网络字节序

    gets(tmpbuff);

    nsize = sendto(sockfd,tmpbuff,strlen(tmpbuff),0,(struct sockaddr *)&recvaddr,sizeof(recvaddr));//sendto将 tmpbuff 中的数据发送给接收方
    //参数依次是 套接字文件描述符、待发送数据的首地址、发送数据的大小、接收方地址信息的指针、接收方地址信息的大小
   
    if(-1 == nsize)
    {
        perror("fail to sendto");
        return -1;
    }

    close(sockfd);

    return 0;
    

}

 recv.c

/*************************************************************************
	> File Name: recv.c
	> Author: yas
	> Mail: rage_yas@hotmail.com
	> Created Time: 2024年03月06日 星期三 22时21分52秒
 ************************************************************************/

#include"head.h"
int main(void)
{
    int ret = 0;
    int sockfd = 0;
    struct sockaddr_in recvaddr;
    struct sockaddr_in sendaddr;
    socklen_t addrlen = sizeof(sendaddr);
    char tmpbuff[1024] = {0};
    ssize_t nsize = 0;

    sockfd = socket(AF_INET,SOCK_DGRAM,0);
    if(-1 == sockfd)
    {
        perror("fail to socket");
        return -1;
    }

    recvaddr.sin_family = AF_INET;
    recvaddr.sin_port = htons(50000);
    recvaddr.sin_addr.s_addr = inet_addr("192.168.1.157");
//设置接收方地址的信息,使用bind 将套接字与接收方的地址绑定
    ret = bind(sockfd,(struct sockaddr *)&recvaddr,sizeof(recvaddr));//bind 参数依次为 套接字文件描述符、指向待绑定地址信息的指针、地址信息的大小
    if(-1 == ret)
    {
        perror("fail to bind");
        return -1;
    }

    nsize = recvfrom(sockfd,tmpbuff,sizeof(tmpbuff),0,(struct sockaddr *)&sendaddr,&addrlen);
    //从套接字接收数据并保存在tmpbuff中
    //recvfrom参数依次为 套接字文件描述符、接收数据的缓冲区、缓冲区大小、标志位、指向发送方地址信息的指针、地址信息的长度
    if(-1 == nsize)
    {
        perror("fail to recvfrom");
        return -1;
    }

    printf("RECV FROM %s:%d>%s\n",inet_ntoa(sendaddr.sin_addr),ntohs(sendaddr.sin_port),tmpbuff);
// 返回发送端的ip地址和端口号
    close(sockfd);

    return 0;
}

 makefile  (使用make 一键编译)

all:send recv 

send:send.c 
	gcc $^ -o $@
recv:recv.c 
	gcc $^ -o $@

.PHONY:
clean:
	rm send recv

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值