【嵌入式Linux】<总览> 网络编程(更新中)

文章目录

前言

一、网络知识概述

1. 网路结构分层

2. socket

3. IP地址

4. 端口号

5. 字节序

二、网络编程常用API

1. socket函数

2. bind函数

3. listen函数

4. accept函数

5. connect函数

6. read和recv函数

7. write和send函数

三、TCP编程

1. TCP介绍

2. TCP通信流程

3. TCP服务端和客户端程序


前言

记录学习嵌入式Linux网络编程的知识重点与难点,若涉及版权问题请联系本人删除!


一、网络知识概述

1. 网路结构分层

①主要存在两种分层模型:OSI七层模型(理论)和TCP/IP四层模型(实际)。

②分层思想:采用分治法,将复杂问题划分为各个层级上的子问题。每一层向上提供服务,同时使用下层提供的服务。

③网络封包和拆包:如下图所示,从主机A传输数据到主机B的流程一般为:主机A的应用层封装好了传输数据后,传输层会给上层数据包添加TCP头部,网络层会给上层数据包添加IP头部,网络接口层会给上层数据包添加对应的头部和尾部(一般为CRC校验);路由器将接收到的帧去掉头部和尾部传输给上一层,传输层将解析IP地址并查表转发,然后继续封装为帧,传输到指定的主机B;主机B逐层拆包,最终在应用层获取接收到的真正数据。

2. socket

①概念:socket是一个特殊的文件描述符,用于网络通信。

②socket分类:

  • 流式套接字(SOCK_STREAM):对应TCP,面向连接、可靠。
  • 数据报套接字(SOCK_DGRAM):对应UDP,无连接、不可靠。
  • 原始套接字(SOCK_RAW):对应多个协议,可以直接访问IP、ICMP,跨过了传输层。

3. IP地址

①概念:IP地址是网络中主机地址的标识。通过IP可以找到对应的主机。

②IP地址分类:

  • IPv4:一个32位(4字节)的整数,每个字节用.来分隔。每个字节的数据范围为0~255。例如: 192.168.5.11  不够用,引入局域网可以解决不够用的问题
  • IPv6:一个128(16字节)的整数,每两个字节为一部分,总共有8部分,每部分用:分隔。例如:2001:0db8:3c4d:0015:0000:0000:1a2f:1a2b   “地球上每一粒沙子都能分配一个”

③特殊的IP地址:

  • 局域网IP:192.XXX.XXX.XXX    10.XXX.XXX.XXX
  • 广播IP:XXX.XXX.XXX.255    255.255.255.255(全网广播)
  • 组播IP:224.XXX.XXX.XXX到239.XXX.XXX.XXX

4. 端口号

①概念:是一个16位的整数,范围:1~65535.

②端口号分类:

  • 众所周知的端口:1~1023. (FTP: 21, SSH: 22, HTTP: 80, HTTPS: 469)
  • 保留端口:1024~5000  不建议使用
  • 可以使用端口:5001~65535

③注意事项:

  • TCP端口和UDP端口是相互独立的。(因为它们在内核中的处理路径不同)
  • 网络通信由IP地址+端口号来决定。IP地址确定主机位置,端口号确定主机中哪个进程来处理。

5. 字节序

①概念:当涉及内存中存取多字节数据时,就会遇到字节序的问题。

②两种字节序:

  • 小端:低字节序内容存储到低地址的内存中。
  • 大端:低字节序内容存储到高地址的内存中。

③注意事项:

  • 一般本地采用小端模式,网络传输采用大端模式。
  • 在发送数据和接收数据前,应该先将本地字节序和网络字节序进行转换。

④主机字节序和网络字节序转换函数:

#include <arpa/inet.h>// 主要用于网络通信过程中IP和端口的转换
uint16_t htons(uint16_t hostshort);   //短整形,主机字节序->网络字节序uint32_t htonl(uint32_t hostlong);    //整形,主机字节序->网络字节序	uint16_t ntohs(uint16_t netshort);    //短整形,网络字节序->主机字节序uint32_t ntohl(uint32_t netlong);     //整形,网络字节序->主机字节序

⑤IP地址转换函数:

inet_pton函数:将IP地址从主机字节序->网络字节序。

【1】头文件:#include <arpa/inet.h>

【2】函数原型:int inet_pton(int af, const char *src, void *dst);

【3】参数说明:

  • af:地址族,填写AF_INET(IPv4)或者AF_INET6(IPv6)
  • src:传入参数,即要转换的IP地址。例如:192.168.5.11
  • dst:传出参数,存放转换后的IP地址。

【4】返回值:成功返回1,第一个参数无效返回-1,第二个参数无效返回0.

inet_ntop函数:将IP地址从网络字节序->主机字节序。

【1】头文件:#include <arpa/inet.h>

【2】函数原型:const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);

【3】参数说明:

  • af:地址族,填写AF_INET(IPv4)或者AF_INET6(IPv6)
  • src:传入参数,其中存储了网络字节序的IP地址。
  • dst:传出参数,存放转换后的IP地址。
  • size:dst指向的内存中最多可以存储多少个字节。

【4】返回值:成功返回指针指向第三个参数对应的地址,失败返回NULL。


二、网络编程常用API

以下函数除read和write外都需包含头文件#include <sys/types.h>、#include <sys/socket.h>

1. socket函数

【1】功能:创建网络套接字。

【2】函数原型:int socket(int domain, int type, int protocol);

【3】参数说明:

domainAF_INETIPv4协议
AF_INET6IPv6协议
AF_LOCAL本地通信
typeSOCK_STREAM流式套接字,对应TCP
SOCK_DGRAM数据报套接字,对应UDP
SOCK_RAW原始套接字
protocol一般写0即可,使用默认协议。非0一般用于原始套接字。

【4】返回值:成功返回套接字fd,失败返回-1。

【5】代码示例:

int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0) {perror("socket error");return -1;
}

2. bind函数

【1】功能:将本地的IP、端口与套接字绑定。

【2】函数原型:int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

【3】参数说明:

sockfd套接字,由socket函数生成
addrstruct sockaddr类型的变量的地址
addrlenaddr指向的内存的地址大小

struct sockaddr结构体:(写数据时一般不用)

struct sockaddr {sa_family_t sa_family;       // 地址族协议, ipv4char        sa_data[14];     // 端口(2字节) + IP地址(4字节) + 填充(8字节)
}

struct sockaddr_in结构体:(常用)一般将端口和IP地址保存在该类型的变量中,然后强转为struct sockaddr类型。(它们的大小完全相同)

struct sockaddr_in
{sa_family_t sin_family;		/* 地址族 */in_port_t sin_port;         /* 端口号, 2字节 -> 网路字节序 */struct in_addr sin_addr;    /* IP地址, 4字节 -> 网络字节序 *//* 填充8字节,初始化为0 */unsigned char sin_zero[sizeof (struct sockaddr) - sizeof(sin_family) -sizeof (in_port_t) - sizeof (struct in_addr)];
};struct in_addr
{in_addr_t s_addr;
};

【4】返回值:成功返回0,失败返回-1。

【5】代码示例:

#define  SERV_PORT    9999
#define  SERV_IP      "192.168.5.12"struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;        //IPv4协议
sin.sin_port = htons(SERV_PROT); //端口号,转化为网络字节序
//IP地址,转化为网络字节序
if (inet_pton(AF_INET, SERV_IP, &sin.sin_addr.s_addr) != 1) {perror("inet_pton error");return -1;
}
if (bind(fd, (struct sockaddr*)&sin, sizeof(sin))) {perror("bind error");return -1;
}

3. listen函数

【1】功能:设置套接字监听。调用之前需要bind绑定。

【2】函数原型:int listen(int sockfd, int backlog);

【3】参数说明:

sockfd监听的文件描述符,由socket函数生成
backlog同时处理的最大连接数,最大值为128

【4】返回值:成功返回0,失败返回-1。

【5】代码示例:

if (listen(fd, 128)) {perror("listen error");return -1;
}

4. accept函数

【1】功能:服务器阻塞等待客户端的连接请求,建立新连接,得到通信使用的套接字。

【2】函数原型:int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

【3】参数说明:

sockfd监听的文件描述符,由socket函数生成
addr传出参数,保存客户端的地址信息
addrlenaddr指向的内存的大小

【4】返回值:成功返回与客户端进行通信的套接字,失败返回-1。

【5】代码示例:

struct sockaddr_in clientAddr;
int clientLen = sizeof(clientAddr);
int cfd = accept(fd, (struct sockaddr*)&clientAddr, &clientLen);
if (cfd < 0) {perror("accept error");return -1;
}

5. connect函数

【1】功能:客户端发起连接请求。成功连接服务器后,客户端会自动随机绑定一个端口。

【2】函数原型:int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

【3】参数说明:

sockfd套接字,由socket函数生成
addr存储要连接的服务端的IP和端口信息(需要网络字节序)
addrlenaddr指向的内存的大小

【4】返回值:成功返回0,失败返回-1。

【5】代码示例:

#define  SERV_PORT    9999
#define  SERV_IP      "192.168.5.12"struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;//IPv4协议
sin.sin_port = htons(SERV_PORT);//目标服务端的端口号,网络字节序
//目标服务端的IP地址,网络字节序
if (inet_pton(AF_INET, SERV_IP, &sin.sin_addr.s_addr) != 1) {perror("inet_pton error");return -1;
}
//调用connect函数
if (connect(fd, (struct sockaddr*)&sin, sizeof(sin)) == -1) {perror("connect error");return -1;
}

6. read和recv函数

【1】功能:接收数据。

【2】函数原型:

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

【3】参数说明:

sockfd用于通信的文件描述符
buf存储接收的数据
lenbuf指向的内存的容量
flags特殊属性,一般不使用,指定为0

【4】返回值:>0表示实际接收的字节数,==0表示对方断开了连接,-1表示失败。

7. write和send函数

【1】功能:接收数据。

【2】函数原型:

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

【3】参数说明:

sockfd用于通信的文件描述符
buf发送的数据
lenbuf的长度
flags特殊属性,一般不使用,指定为0

【4】返回值:>0表示实际发送的字节数(与len相等),-1表示失败。


三、TCP编程

1. TCP介绍

TCP(Transmission Control Protocol)是面向连接的、可靠的、基于字节流的传输层通信协议。

  • 面向连接:建立连接需要三次握手,断开连接需要四次挥手。
  • 可靠安全:在TCP通信过程中,对每个发送的数据包都会进行校验,若数据丢失则重传。
  • 流式传输:发送端和接收端的处理速度、数据量都可以不一致。

2. TCP通信流程

参考爱编程的大丙:

3. TCP服务端和客户端程序

服务端程序:接收客户端数据并打印,同时将收到的数据重新发回客户端。

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>#define SERV_PORT   9999int main(int argc, char **argv)
{/* 1.创建TCP的套接字 */int fd = socket(AF_INET, SOCK_STREAM, 0);if (fd == -1) {perror("server socket error");return -1;}/* 2.绑定IP和端口号 */struct sockaddr_in addr;memset(&addr, 0, sizeof(addr));addr.sin_family = AF_INET;addr.sin_port = htons(SERV_PORT);addr.sin_addr.s_addr = INADDR_ANY;//INADDR_ANY宏表示本机所有IPint ret = bind(fd, (struct sockaddr*)&addr, sizeof(addr));if (ret == -1) {perror("server bind error");return -1;}/* 3.设置监听 */ret = listen(fd, 128);if (ret == -1) {perror("server listen error");return -1;}/* 4.等待客户端连接 */struct sockaddr_in clientAddr;int clientLen = sizeof(clientAddr);int cfd = accept(fd, (struct sockaddr*)&clientAddr, &clientLen);if (cfd == -1) {perror("server accept error");return -1;}//打印客户端信息char ip[24] = {0};printf("客户端IP: %s, 端口: %d\n",inet_ntop(AF_INET, &clientAddr.sin_addr.s_addr, ip, sizeof(ip)),ntohs(clientAddr.sin_port));/* 5.与客户端通信 */while (1) {//接收数据char buf[1024];memset(buf, 0, sizeof(buf));ret = read(cfd, buf, sizeof(buf));if (ret == 0) {printf("服务端:与客户端断开连接\n");break;} else if (ret < 0) {perror("server read error");break;} else {//打印接收数据,并重新发回接收的数据printf("服务端接收: %s\n", buf);write(cfd, buf, sizeof(buf));}}/* 6.关闭文件描述符 */close(cfd);close(fd);return 0;
}

客户端程序:每1秒发送指定数据,同时接收来自服务端的数据。

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>#define SERV_PORT   9999
#define SERV_IP     "192.168.124.6"int main(int argc, char **argv)
{/* 1.创建TCP的套接字 */int fd = socket(AF_INET, SOCK_STREAM, 0);if (fd == -1) {perror("client socket error");return -1;}/* 2.与服务端建立连接 */struct sockaddr_in addr;memset(&addr, 0, sizeof(addr));addr.sin_family = AF_INET;addr.sin_port = htons(SERV_PORT);inet_pton(AF_INET, SERV_IP, &addr.sin_addr.s_addr);int ret = connect(fd, (struct sockaddr*)&addr, sizeof(addr));if (ret == -1) {perror("client connect error");return -1;}//打印连接的服务端信息printf("连接的服务端IP: %s, 端口: %d\n", SERV_IP, SERV_PORT);/* 3.与服务端通信 */int number = 0;while (1) {//发送数据char buf[1024] = {0};sprintf(buf, "客户端: number = %d\n", number++);write(fd, buf, sizeof(buf));//接收数据memset(buf, 0, sizeof(buf));ret = read(fd, buf, sizeof(buf));if (ret == 0) {printf("客户端:与服务端断开连接\n");break;} else if (ret < 0) {perror("client read error");break;} else {printf("客户端接收: %s\n", buf);}sleep(1);//发送数据慢一些}/* 4.关闭文件描述符 */close(fd);return 0;
}

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

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

相关文章

基于vite的vue脚手架工具整合:ts、jsx、eslint、prettier、stylelint、tailwind...

为了帮助vue新手更高效的学习vue3的基础知识、组件开发以及项目方案整合&#xff0c;小卷给大家整理了一个10分钟搞定《基于vite的vue脚手架工具整合》的教程。所有工具都是目前最新的版本&#xff0c;实践和调试过&#xff0c;没有一行多余的配置。

C语言之qsort函数

一、qsort 1.库函数qsort qsort是库函数&#xff0c;直接可以用来排序数据&#xff0c;底层使用的是快速排序。 qsort函数可以排序任意类型的数据。 2.头文件 #include<stdlib.h> 3.参数讲解 void*类型的指针是无具体类型的指针&#xff0c;这种类型的指针的不能直接解…

逻辑分析仪小试(DOING)

PDD买的&#xff0c;价格很nice 有一个小遗憾&#xff0c;接口是mini-usb&#xff0c;这种线找了半天&#xff0c;终于发出来一根&#xff0c;插上去直接灯就亮了。 网上找了一些教程&#xff0c;才发现这个原来是美国saleae的山寨产品。。。但是群众们都一片叫好。 所以配套…

【填坑指南】PHP8报:Unable to load dynamic library ‘zip.so’ 错误

1.原因分析 这种情况多数发生在PHP安装时因为各种原因失败后&#xff0c;残余的库与最后安装的PHP版本不兼容导致的。 2.我的路径 一开始我按照以前摸索出来的安装PHP7.3的成功经验来编译方法安装PHP8.3&#xff0c;发现以前的套路已经失效了。反复重装PHP8.3失败后&#xf…

每日复盘-20240715

20240715 六日涨幅最大: ------1--------300807--------- 天迈科技 五日涨幅最大: ------1--------300807--------- 天迈科技 四日涨幅最大: ------1--------300807--------- 天迈科技 三日涨幅最大: ------1--------300713--------- 英可瑞 二日涨幅最大: ------1--------3007…

广告人的的自白,我们是怎么看“创意”这回事的?

作为广告行业的一员&#xff0c;广告创意确实是这个行业中非常核心且充满魅力的一部分。 创意的本质在于能够触动人心&#xff0c;与目标受众产生共鸣&#xff0c;并且有效地传达品牌或产品的信息。 作为一个多年的广告人&#xff0c;下面是我对创意的来源和什么是成功的创意…

UE4-初见虚幻引擎

一.创建自己的工程 1.启动 a.通过桌面双击图标来打开对应版本的虚幻引擎 b.通过EPIC启动器开启动虚幻引擎 2.选择或新建项目 ps:高版本虚幻编辑器可以打开低版本的虚幻项目&#xff0c;但是高版本虚幻的项目不可以由低版本的虚幻编辑器打开。 3. 选择要打开的项目 4.选择模版 选…

Github2.1万星!开发者的“瑞士军刀” 开源!

转载自&#xff1a;GitHub好项目 DevToys 是一个专为开发者设计的实用工具集&#xff0c;它集合了多种开发中常用的功能&#xff0c;如JSON格式化、文本比较、正则表达式测试等&#xff0c;旨在帮助开发者提高编程效率。 镜像代码&#xff1a; http://www.gitpp.com/fm/devt…

Kotlin标准函数(语法糖)let with run also apply快速讲解

目录 1、知识储备——扩展函数 原理 定义扩展函数 调用扩展函数 2、返回值为上下文对象的标准函数 apply also 3、返回值为Lambda表达式结果 let run with 4、一表总结 1、知识储备——扩展函数 原理 Kotlin 在不继承父类或实现接口下&#xff0c;也能扩展一个类的…

PHP中的函数与调用:深入解析与应用

目录 一、函数基础 1.1 函数的概念 1.2 函数的定义 1.3 函数的调用 二、PHP函数的分类 2.1 内置函数 2.2 用户自定义函数 2.3 匿名函数 2.4 递归函数 2.5 回调函数 2.6 魔术方法 三、函数的参数与返回值 3.1 参数传递 3.2 返回值 四、函数的高级特性 4.1 可变函…

川大智胜果然开盘涨停,这就是A股的尿性!

昨天特朗普被刺杀未遂&#xff0c;提前赢得了大选。今天A股的川大智胜(002253)开盘即涨停&#xff0c;毫无悬念。 不要觉得奇怪&#xff0c;这就是缅A一直以来的尿性&#xff01;什么炒龙凤&#xff0c;炒麻将&#xff0c;炒数字&#xff0c;炒AI&#xff0c;炒美国大选&#…

ROM修改进阶教程------深度解析小米设备锁机型不解锁bl 刷写特殊类固件的步骤

在玩机过程中会遇到很多自己机型忘记密码或者手机号不用导致机型出现账号锁。无法正常使用。那么此类机型如果无法正常售后解锁。只能通过第三方渠道。例如在早期小米机型有强解bl锁资源。然后刷入完美解锁包。这种可以登陆新账号。但后期新机型只能通过修改分区来屏蔽原设备锁…

CORDIC Translate

随便记录一下下&#xff1a; Cordic IP核使用说明以及避坑记录-CSDN博客 本次只用到了Translate&#xff0c;记录一下自己遇到的坑坑 实际配置&#xff1a; timescale 1ns / 1nsmodule cordic_tb();reg clk;wire m_axis_dout_tvalid;reg s_axis_cartesian_tvalid 0;wire [31…

快速上手electron

官方文档: https://www.electronjs.org/zh/docs/latest/ 搭建项目 新建文件夹并初始化项目 mkdir my-electron-app && cd my-electron-app npm init -y注意:新生成的package.json的author(作者)和description(描述)字段要填写补全,不然后期打包会打不了 将package.…

CUTLASS

文章目录 1、关于 CUTLASS2、CUTLASS 3.5中的新增功能3、性能4、兼容性4、操作系统5、硬件6、目标架构7、文档8、资源9、构建 CUTLASS10、项目结构11、CUTLASS模板库CUTLASS SDK示例工具测试 12、性能分析13、构建所有GEMM和卷积内核&#xff08;构建时间长&#xff09;14、构建…

银河麒麟高级服务器操作系统V10加固操作指南

1:检查系统openssh安全配置: 2:检查是否设置口令过期前警告天数: 3:检查账户认证失败次数限制: 修改/etc/pam.d/system-auth文件中deny的参数即可 4:检查是否配置SSH方式账户认证失败次数限制:

StarRocks部署高可用 FE 集群

一、准备工作 1.1 部署规划 这里我打算部署存算一体模式&#xff0c;三节点。即三个FE节点&#xff0c;三个BE节点。假设三台IP分别为&#xff1a;10.10.10.50、10.10.10.51、10.10.10.52 我将采用三台centos7.9进行部署&#xff0c;单台配置为128C 256G 3T。 1.2 服务器检查…

拓展神经网络八股(入门级)

自制数据集 minst等数据集是别人打包好的&#xff0c;如果是本领域的数据集。自制数据集。 替换 把图片路径和标签文件输入到函数里&#xff0c;并返回输入特征和标签 要生成.npy格式的数据集&#xff0c;在进行读入训练集。 只需要把图片灰度值数据拼接到特征列表&#xff0…

进程间通信(下)

system V共享内存 共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间&#xff0c;这些进程间数据传递不再涉及到内核&#xff0c;换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据 共享内存示意图 通过上面的图&#xff0c;我们不难想到…

linux的学习(三):用户权限,查找,压缩命令

简介 关于用户权限&#xff0c;查找和压缩解压缩命令的简单使用 用户管理命令 useradd useradd&#xff1a;添加新用户&#xff0c;要root权限才能使用 useradd -g 组名 用户名&#xff1a;可以添加到组 创建成功会在 /home下有用户的主目录 passwd passwd 用户名&#x…