嵌入式养成计划-29-网络编程----TCP与UDP的基础模型

news2024/11/26 21:37:04

Linux下,基于TCP与UDP协议,不同进程下单线程通信服务器

Linux下,基于TCP与UDP协议,不同进程下单线程通信服务器

六十五、TCP与UDP的基础模型

1. socket

1.1 套接字概念

  • 最早的套接字和共享内存,消息队列,管道一样,只能实现一个主机内部的进程间通信。
  • 后期加入了TCP/IP协议,使的套接字能够支持不同主机之间的进程间通信。
  • socket函数,可以在内核空间中创建两块缓冲区,供于发送数据,接收数据。
    在这里插入图片描述

1.2 socket 函数

功能:
	在内核空间中创建两个缓冲区(发送缓冲区,接收缓冲区),返回该缓冲区的文件描述符到用户空间中;
原型:
       #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>

       int socket(int domain, int type, int protocol);
参数:
    int domain:地址族,协议族。
       Name                Purpose                          Man page
       AF_UNIX, AF_LOCAL   Local communication              unix(7)
       AF_INET             IPv4 Internet protocols          ip(7)
       AF_INET6            IPv6 Internet protocols          ipv6(7)
    int type:  
        SOCK_STREAM:字节流式套接字,流式套接字,默认使用TCP协议;
        SOCK_DGRAM:  数据报式套接字,报式套接字,默认使用UDP协议;
        SOCK_RAW:    原始套接字,协议需要在第三个参数手动指定.
        
    int protocol:默认协议,填0;
        IPPROTO_TCP  IPPROTO_UDP  IPPROTO_IP
返回值:
    成功,返回一个新的文件描述符;
    失败,返回-1,更新errno;

2. TCP编程

2.1 TCP流程图

在这里插入图片描述

2.2 TCP 中的函数

2.2.1 socket

功能:
	在内核空间中创建两个缓冲区(发送缓冲区,接收缓冲区),返回该缓冲区的文件描述符到用户空间中;
原型:
       #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>

       int socket(int domain, int type, int protocol);
参数:
    int domain:地址族,协议族。
       Name                Purpose                          Man page
       AF_UNIX, AF_LOCAL   Local communication              unix(7)
       AF_INET             IPv4 Internet protocols          ip(7)
       AF_INET6            IPv6 Internet protocols          ipv6(7)
    int type:  
        SOCK_STREAM:字节流式套接字,流式套接字,默认使用TCP协议;
        SOCK_DGRAM:  数据报式套接字,报式套接字,默认使用UDP协议;
        SOCK_RAW:    原始套接字,协议需要在第三个参数手动指定.
        
    int protocol:默认协议,填0;
        IPPROTO_TCP  IPPROTO_UDP  IPPROTO_IP
返回值:
    成功,返回一个新的文件描述符;
    失败,返回-1,更新errno;

2.2.2 bind

功能:
	绑定地址信息到指定套接字上;
原型:
       #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>

       int bind(int sockfd, const struct sockaddr *addr,
 socklen_t addrlen);
参数:
    int sockfd:指定要绑定到哪个套接字上,填对应的文件描述符;
    struct sockaddr *addr:通用地址信息结构体,真实的地址信息结构体根据地址族指定。
                            手动填充上地址信息(例如:IP和端口),给bind函数绑定使用;
        AF_INET: man 7 IP
           struct sockaddr_in {
               sa_family_t    sin_family; /* address family: AF_INET */     必须填AF_INET
               in_port_t      sin_port;   /* port in network byte order */  端口号的网络字节序(1024~49151struct in_addr sin_addr;   /* internet address */      IP地址的网络字节序,(本机IP:ifconfig查看)       
           };

           /* Internet address. */
           struct in_addr {
               uint32_t       s_addr;     /* address in network byte order */
           };
       AF_INET6: man 7 ipv6          
    socklen_t addrlen:真实的地址信息结构体的大小,sizeof(struct sockaddr_in);
返回值:
    成功,返回0;
    失败,返回-1,更新errno;

报错解释:bind: Address already in use ---->原因:代码异常退出后,端口号会在30s~3min不等的时间释放。

2.2.3 listen

功能:
	将套接字设置为被动监听状态;
    让内核去维护两个队列:未完成连接的队列,已完成连接的队列
原型:
       #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>

       int listen(int sockfd, int backlog);
参数:
    int sockfd:指定要转换成被动监听状态的文件描述符;
    int backlog:指定未完成连接队列的容量,不要填01即可,一般填128;
返回值:
    成功,返回0;
    失败,返回-1,更新errno;

2.2.4 accept(阻塞函数)

功能:
	阻塞函数,阻塞等待客户端连接成功,从已完成连接的队列中获取一个客户端信息,生成一个新的文件描述符。
    该文件描述符才是与客户端通信的文件描述符;
原型:
       #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>

       int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
参数:
    int sockfd:被转换成被动监听状态的文件描述符;
    struct sockaddr *addr:通用地址信息结构体,真实的地址信息结构体根据地址族指定。
                            存储获取到的客户端的地址信息;若不想获取,则填NULL;
        AF_INET: man 7 IP
           struct sockaddr_in {
               sa_family_t    sin_family; /* address family: AF_INET */     必须填AF_INET
               in_port_t      sin_port;   /* port in network byte order */  端口号的网络字节序(1024~49151struct in_addr sin_addr;   /* internet address */      IP地址的网络字节序,(本机IP:ifconfig查看)       
           };

           /* Internet address. */
           struct in_addr {
               uint32_t       s_addr;     /* address in network byte order */
           };   
    socklen_t *addrlen:真实的地址信息结构体的大小,注意是指针类型,若第二个参数填NULL,则该参数也填NULL;  
返回值:
    成功,返回新的通信套接字文件描述符; 该文件描述符才是与客户端通信的文件描述符;
    失败,返回-1,更新errno;

2.2.5 recv

功能:
	接收数据;
原型:
       #include <sys/types.h>
       #include <sys/socket.h>

       ssize_t recv(int sockfd, void *buf, size_t len, int flags);
参数:
    int sockfd:指定从哪个套接字维护的缓冲区中读取数据;
    void *buf:存储接收到的数据,void*:可以接收任意类型数据;
    size_t len:指定要接收多少个字节的数据;
    int flags:
            0:阻塞方式,当缓冲区中没有数据的时候,该函数阻塞; 若flags==0, 则recv函数等价于read函数;
            MSG_DONTWAIT:非阻塞方式,当当缓冲区中没有数据的时候,该函数不阻塞;且函数运行失败;
返回值:
    >0, 成功读取到的字节数;
    =0,在流失套接字中,若对端关闭,则返回0;
    =-1, 函数运行失败,更新errno;
    
recv(sockfd, buf, len, flags);
 等价于 recvfrom(sockfd, buf, len, flags, NULL, NULL);
  • recv函数能否替换成其他函数?
    可以,当recv函数最后一个参数填0,可以替换成read函数,
    当recvfrom后面两个参数填NULL的时候,等价于recv函数,所以可以替换成recvfrom

2.2.6 send

功能:
	发送数据;
原型:
       #include <sys/types.h>
       #include <sys/socket.h>

       ssize_t send(int sockfd, const void *buf, size_t len, int flags);
参数:
    int sockfd:指定向哪个套接字维护的缓冲区中写入数据;
    void *buf:指定要发送的数据的首地址,void*:可以发送任意类型数据;
    size_t len:指定要发送多少个字节的数据;
    int flags:
            0:阻塞方式,当缓冲区中满的时候,该函数阻塞; 若flags==0, 则send函数等价于write函数;
            MSG_DONTWAIT:非阻塞方式,当缓冲区中满的时候,该函数不阻塞;且函数运行失败;    
返回值:
    >0, 成功发送的字节数;
    =-1,函数运行失败,更新errno;

send(sockfd, buf, len, flags);
 等价于 sendto(sockfd, buf, len, flags, NULL, 0);
  • send函数能否替换成其他函数?
    可以,当send函数最后一个参数填0,可以替换成write函数,
    当sendto后面两个参数填NULL, 0 的时候,等价于send函数,所以可以替换成sendto

2.2.7 connect

功能:
	连接服务器;
原型:
       #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>

       int connect(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
参数:
    int sockfd:指定要通过哪个文件描述符连接服务器;
    struct sockaddr *addr:通用地址信息结构体,真实的地址信息结构体根据地址族指定。
                            手动填充上服务器的地址信息(例如:IP和端口),给connect函数绑定使用; 
                            想要连接哪个服务器就填哪个服务器的地址信息
        AF_INET: man 7 IP
           struct sockaddr_in {
               sa_family_t    sin_family; /* address family: AF_INET */     必须填AF_INET
               in_port_t      sin_port;   /* port in network byte order */  端口号的网络字节序(1024~49151struct in_addr sin_addr;   /* internet address */      IP地址的网络字节序,(本机IP:ifconfig查看)       
           };

           /* Internet address. */
           struct in_addr {
               uint32_t       s_addr;     /* address in network byte order */
           };
    socklen_t addrlen:真实的地址信息结构体的大小,sizeof(struct sockaddr_in);
返回值:
    成功,返回0;
    失败,返回-1,更新errno;

3. UDP编程

3.1 UDP流程图

在这里插入图片描述

3.2 UDP搭建

3.2.1 socket

功能:
	在内核空间中创建两个缓冲区(发送缓冲区,接收缓冲区),返回该缓冲区的文件描述符到用户空间中;
原型:
       #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>

       int socket(int domain, int type, int protocol);
参数:
    int domain:地址族,协议族。
       Name                Purpose                          Man page
       AF_UNIX, AF_LOCAL   Local communication              unix(7)
       AF_INET             IPv4 Internet protocols          ip(7)
       AF_INET6            IPv6 Internet protocols          ipv6(7)
    int type:  
        SOCK_STREAM:字节流式套接字,流式套接字,默认使用TCP协议;
        SOCK_DGRAM:  数据报式套接字,报式套接字,默认使用UDP协议;
        SOCK_RAW:    原始套接字,协议需要在第三个参数手动指定.
        
    int protocol:默认协议,填0;
        IPPROTO_TCP  IPPROTO_UDP  IPPROTO_IP
返回值:
    成功,返回一个新的文件描述符;
    失败,返回-1,更新errno;

3.2.2 bind

功能:
	绑定地址信息到指定套接字上;
原型:
       #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>

       int bind(int sockfd, const struct sockaddr *addr,
 socklen_t addrlen);
参数:
    int sockfd:指定要绑定到哪个套接字上,填对应的文件描述符;
    struct sockaddr *addr:通用地址信息结构体,真实的地址信息结构体根据地址族指定。
                            手动填充上地址信息(例如:IP和端口),给bind函数绑定使用;
        AF_INET: man 7 IP
           struct sockaddr_in {
               sa_family_t    sin_family; /* address family: AF_INET */     必须填AF_INET
               in_port_t      sin_port;   /* port in network byte order */  端口号的网络字节序(1024~49151struct in_addr sin_addr;   /* internet address */      IP地址的网络字节序,(本机IP:ifconfig查看)       
           };

           /* Internet address. */
           struct in_addr {
               uint32_t       s_addr;     /* address in network byte order */
           };
       AF_INET6: man 7 ipv6          
    socklen_t addrlen:真实的地址信息结构体的大小,sizeof(struct sockaddr_in);
返回值:
    成功,返回0;
    失败,返回-1,更新errno;

3.2.3 recvfrom

功能:
	接收数据的同时可以获取到该数据包从哪里来,即可以知道发送方的地址信息;
原型:
       #include <sys/types.h>
       #include <sys/socket.h>

       ssize_t recv(int sockfd, void *buf, size_t len, int flags);

       ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                        struct sockaddr *src_addr, socklen_t *addrlen);
参数:
    int sockfd:指定从哪个套接字维护的缓冲区中读取数据;
    void *buf:存储接收到的数据,void*:可以接收任意类型数据;
    size_t len:指定要接收多少个字节的数据;
    int flags:
            0:阻塞方式,当缓冲区中没有数据的时候,该函数阻塞; 若flags==0, 则recv函数等价于read函数;
            MSG_DONTWAIT:非阻塞方式,当当缓冲区中没有数据的时候,该函数不阻塞;且函数运行失败;
    struct sockaddr *src_addr:通用地址信息结构体,真实的地址信息结构体根据地址族指定。
                                用于存储发送方的地址信息的,即用于存储这个包是从谁那里发送过来的。若不想接收则填NULL;
        AF_INET: man 7 IP
           struct sockaddr_in {
               sa_family_t    sin_family; /* address family: AF_INET */     必须填AF_INET
               in_port_t      sin_port;   /* port in network byte order */  端口号的网络字节序(1024~49151struct in_addr sin_addr;   /* internet address */      IP地址的网络字节序,(本机IP:ifconfig查看)       
           };

           /* Internet address. */
           struct in_addr {
               uint32_t       s_addr;     /* address in network byte order */
           };   
    socklen_t *addrlen:真实的地址信息结构体的大小,注意是指针类型,若第二个参数填NULL,则该参数也填NULL;  
返回值:
    >0, 成功读取到的字节数;
    =0,但是只有在流失套接字中,若对端关闭,则返回0;
    =-1, 函数运行失败,更新errno;

recv(sockfd, buf, len, flags);
等价于 recvfrom(sockfd, buf, len, flags, NULL, NULL);

3.2.4 sendto

功能:
	发送数据给指定该数据包应该发给谁,即指定接收方的地址,必须指定清楚这个包该发给谁
原型:
       #include <sys/types.h>
       #include <sys/socket.h>

       ssize_t send(int sockfd, const void *buf, size_t len, int flags);

       ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                      const struct sockaddr *dest_addr, socklen_t addrlen);
参数:
    int sockfd:指定向哪个套接字维护的缓冲区中写入数据;
    void *buf:指定要发送的数据的首地址,void*:可以发送任意类型数据;
    size_t len:指定要发送多少个字节的数据;
    int flags:
            0:阻塞方式,当缓冲区中满的时候,该函数阻塞; 若flags==0, 则send函数等价于write函数;
            MSG_DONTWAIT:非阻塞方式,当缓冲区中满的时候,该函数不阻塞;且函数运行失败;  
    struct sockaddr *src_addr:通用地址信息结构体,真实的地址信息结构体根据地址族指定。
                                指定该数据包应该发给谁,即指定接收方的地址信息,想发给谁填谁的地址信息;
        AF_INET: man 7 IP
           struct sockaddr_in {
               sa_family_t    sin_family; /* address family: AF_INET */     必须填AF_INET
               in_port_t      sin_port;   /* port in network byte order */  端口号的网络字节序(1024~49151struct in_addr sin_addr;   /* internet address */      IP地址的网络字节序,(本机IP:ifconfig查看)       
           };

           /* Internet address. */
           struct in_addr {
               uint32_t       s_addr;     /* address in network byte order */
           };   
    socklen_t addrlen:真实的地址信息结构体的大小;              
返回值:
    >0, 成功发送的字节数;
    =-1,函数运行失败,更新errno; 

send(sockfd, buf, len, flags);
等价于 sendto(sockfd, buf, len, flags, NULL, 0);

网络调试工具— —飞机的用法

  • 注意: 关闭计算机的杀毒软件,电脑管家,防火墙

在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1023559.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

坚鹏:郴州市银行业协会BLM银行数字化转型战略培训圆满结束

郴州市银行业协会BLM银行数字化转型战略培训圆满结束 在数字化转型背景下&#xff0c;郴州市银行业协会为了落实监管政策《关于银行业保险业数字化转型的指导意见》&#xff0c;充分认识到学习银行银行数字化转型战略的价值和重要性&#xff0c;特别举办《2023年数字化转型战略…

10.4 稳压管稳压电路

虽然整流滤波电路能将正弦交流电压变换成较为平滑的直流电压&#xff0c;但是&#xff0c;一方面&#xff0c;由于输出电压平均值取决于变压器副边电压有效值&#xff0c;所以当电网电压波动时&#xff0c;输出电压平均值将随之产生相应的波动&#xff1b;另一方面&#xff0c;…

Qt --- Day03

<?xml version"1.0" encoding"UTF-8"?> <ui version"4.0"><class>Widget</class><widget class"QWidget" name"Widget"><property name"geometry"><rect><x>0…

halcon对比度增强

halcon对比度增强 emphasize open_framegrabber (GigEVision2, 0, 0, 0, 0, 0, 0, progressive, -1, default, -1, false, default, b0b35368a72b_GEV_MVCS00410GM, 0, -1, AcqHandle) grab_image_start (AcqHandle, -1)while (true)grab_image_async (Image, AcqHandle, -1)d…

【VS2019 Qt5 VTK9.2】界面编程问题解决记录

一、Qt和VTK相关问题及解决 1. Widget和Viewer的设置顺序 imageViewer->SetupInteractor(renderWindow->GetInteractor());ui.qvtkWidget->setRenderWindow(imageViewer->GetRenderWindow());二者顺序决定了能否正确显示。 参考&#xff1a;QVTKWidget和vtkImageV…

RocketMQ 源码分析——分布式事务方案

文章目录 消息队列解决事务存在的问题RocketMQ的分布式事务方案RocketMQ的分布式事务案例代码分布式事务源码分析消息发送源码分析确认/回滚源码分析回查源码分析 总结 消息队列解决事务存在的问题 如果使用消息队列解决事务在哪个阶段向MQ发送消息&#xff1f; 先扣款后再向R…

计算机算法分析与设计(3)---循环赛日程表(含代C++码)

循环赛日程表 一、内容概述二、代码实现2.1 分治代码2.2 结果图 一、内容概述 二、代码实现 2.1 分治代码 // 循环赛日程表 #include<iostream> #include<cmath> using namespace std;void schedule(int k, int n, int** array) // 数组下标从1开始 {for (int …

【操作系统】聊聊文件系统是如何工作的

文件系统其实是操作系统中存储的核心、计算、网络。除了使用寄存器、内存可以临时存储数据&#xff0c;使用磁盘持久化存储更重要。 磁盘为系统提供了数据持久化功能。文件系统在磁盘的基础上&#xff0c;抽象出了一个管理文件的树状结构 索引节点和目录项 Linux中一切皆是文…

HTTP请求、响应详解

目录 一、HTTP请求详解 1.1 认识请求“报头”&#xff08;header&#xff09; 1.2 认识请求“正文”&#xff08;body&#xff09; 1.2.1 application/x-www-form-urlencoded 1.2.2 multipart/form-data 1.2.3 application/json 二、HTTP响应详解 2.1 认识状态码 2.2 认识响…

Centos7配置国内yum源

目录 备份原系统中的repo文件配置国内开源镜像重新生成yum缓存 备份原系统中的repo文件 cd /etc/yum.repos.d/mkdir repo_bakmv *.repo repo_bak/配置国内开源镜像 到网易和阿里开源镜像站点下载系统对应版本的repo文件 curl -O http://mirrors.aliyun.com/repo/Centos-7.re…

com.google.gson.internal.LinkedTreeMap cannot be cast to XXX

起因是在对google商品做本地缓存时&#xff0c;上线后发现的bug 刚开始非常自信&#xff0c;debug没问题线上有问题&#xff0c;大概率就是混淆文件没有添加keep&#xff0c;于是本地添加对SDK中类的keep&#xff0c;本地打包release验证&#xff0c;不出意外还是崩溃 仔细看…

GEE:Bfast时间序列扰动检测

本文记录了 Google Earth Engine &#xff08;GEE&#xff09; 上 Bfast 时间序列检测的APP和gitHub链接。 文章目录 一、APP Bfast APP&#xff1a; [https://andreim.users.earthengine.app/view/bfastmonitor](https://andreim.users.earthengine.app/view/bfastmonitor)git…

C语言——通讯录管理系统

通讯录管理系统项目简介 功能说明 控制台黑窗口实现程序需要满足以下几个功能 程序开始运行时首先显示选择菜单界面&#xff0c;根据用户输入确定实现何种功能 程序界面 代码实现 多文件实现 和之前写的实战项目类似&#xff0c;这里同样采用多文件实现的方式 多文件写代码…

5G先锋开道,护航出行安全

“道路千万条&#xff0c;安全第一条”。 交通作为城市生命线“主动脉”&#xff0c;承载着助推经济发展的重要使命。构建“预、防、治”全周期交通管理&#xff0c;推进城市精细化管理刻不容缓。 为全面加强交通安全监管体系&#xff0c;天津某交管局决策对新区街道4000多个路…

计算机二级-简单应用题

题目要求 编写代码&#xff0c;以实现如下功能&#xff1a; 键盘输入小明学习的课程名称及考分等信息&#xff0c;信息间采用空格分隔&#xff0c;每个课程一行&#xff0c;空行回车结束录入&#xff0c;示例格式如下&#xff1a; 数学 90 语文 95 英语 86 物理 84 生物 87 屏幕…

(二)随机变量的数字特征:探索概率分布的关键指标

文章目录 &#x1f34b;1. 随机变量的数学期望&#x1f34b;1.1 离散型随机变量的数学期望&#x1f34b;1.2 连续型随机变量的数学期望 &#x1f34b;2. 随机变量函数的数学期望&#x1f34b;2.1 一维随机变量函数的数学期望&#x1f34b;2.2 二维随机变量函数的数学期望 &…

机器学习算法基础--逻辑回归

目录 1.数据收集及处理 2.数据提取及可视化 3.逻辑回归训练样本并且测试 4.绘制散点决策边界 逻辑回归的方法已经在数学建模里面讲过了&#xff0c;这里就不多讲了。 本篇我们主要是利用逻辑回归的方法来求解分类问题。 1.数据获取及处理 import pandas as pd from sklearn…

蓝桥杯2023年第十四届省赛真题-像素放置

目录 蓝桥杯2023年第十四届省赛真题-像素放置 题目描述 输入格式 输出格式 样例输入 样例输出 提示 【思路解析】 【代码实现】 大家觉得写得可以的话&#xff0c;可以加入QQ群907575059. 蓝桥杯2023年第十四届省赛真题-像素放置 时间限制: 3s 内存限制: 320MB 提交:…

QT--day3

2> 完成文本编辑器的保存工作 widget.cpp #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }void Widget::on_fontbtn_cl…

uniapp 实现不同用户展示不同的tabbar(底部导航栏)

一、背景 最近在做一个uniapp开发的小程序遇到一个需求&#xff0c;希望不同用户登录后展示不同的tabbar页面&#xff0c;但是uniapp项目中的pages.json是只有一个list数组的&#xff0c;并且是不能写成动态效果&#xff0c;为了实现这个需求&#xff0c;便自定义了tabbar组件 …