Linux网络编程 socket编程篇(一) socket编程基础
目录
一、预备知识
1.IP地址
2.端口号
3.网络通信
4.TCP协议简介
5.UDP协议简介
6.网络字节序
二、socket
1.什么是socket(套接字)?
2.为什么要有套接字?
3.套接字的主要类型
拓】网络套接字
三、socket API
1.socket API是什么?
2.为什么要有Socket API?
3.Socket编程常见API
3.1 socket()
int socket(int domain, int type, int protocol);
3.2 bind()
3.3 listen ()
3.4 accept()
3.5 connect ()
四、sockaddr
1. 是什么?
2. 为什么?
3. sockaddr的分类
4.Linux中sockaddr的声明
5.创建并填充struct sockaddr_in
6.使用sockaddr传参
一、预备知识
1.IP地址
1.1 是什么?
IP地址是在IP协议中, 用来标识网络中不同主机的地址。
1.2 IPv4 & IPv6
- 对于IPv4来说, IP地址是一个4字节, 32位的整数。通常使用 "点分十进制" 的字符串表示IPv4地址, 例如 123.145.67.89 ; 用点分割的每一个数字表示一个字节, 范围是 0 - 255;
- 对于IPv6来说, IP地址长度为16字节128位,是IPv4地址长度的4倍。于是IPv4点分十进制格式不再适用,采用十六进制表示。具体表示方式请看:IPv6- 百度百科
1.3源IP和目的IP
- 在IP数据报(在网络层向数据链路层传递数据时封装)的首部中, 有两个IP地址, 分别叫做源IP地址, 和目的IP地址。
- 源IP地址:发送消息的主机地址。
- 目的IP地址:接收消息的主机地址。
2.端口号
2.1 是什么?
端口号是一个2字节16位的整数,用来标识一个进程。
2.2 pid 表示唯一一个进程; 端口号也是唯一表示一个进程. 那么这两者之间是怎样的关系?
- "端口号" 和 "进程pid"没有任何关系。
端口号用于网络通信,而进程pid用于进程管理,网络通信和进程管理是两个毫不相干的模块。之所以不用pid来代替端口号的功能是为了功能解耦,减少系统的耦合度。- 不是所有的进程需要端口号,但是所有的进程都需要PID。
- 一个进程可以有多个端口号; 但一个端口号只能被一个进程占用。
2.3 理解源端口号和目的端口号
- 传输层协议(TCP和UDP)的数据段中有两个端口号,分别叫做源端口号和目的端口号。 就是在描述 "数据是谁发的, 要发给谁"。
- 源端口号:发送消息的进程的端口号。
- 目的端口号:接收消息的进程的端口号。
3.网络通信
3.1 是什么?
网络通信的本质就是进程间通信。
3.2 为什么?
发送数据的主机由进程发出数据,接收数据的主机也要靠进程处理数据。简化后其实就是一个进程发出数据,另一个进程处理数据。所以说网络通信的本质就是进程间通信。
3.3 网络通信时如何保证IP地址+端口号能找到指定进程?
- 客户端进程给服务端进程发信息
服务端进程一般都是一经启动,避免关闭,所以服务端进程的端口号不会随意改变。所以客户端进程能根据下载软件时得到的IP地址+端口号找到服务端进程。- 服务端进程给客户端进程发信息
软件被用户打开后,客户端进程和端口号被创建,此时客户端进程要先向服务端发信息来获取数据,所以服务端进程就得到了客户端进程的IP地址+端口号,往后服务端进程能根据客户端进程的IP地址+端口号找到客户端进程。(所以我们打开软件后,通常会加载一会)
3.4 OS如何根据端口号找到指定的进程?
底层采用哈希的方式建立了端口号和进程PID或PCB之间的映射关系,当底层拿到端口号时就可以在哈希表中根据端口号找到对应的进程。
3.5 网络通信是双方的
当一台主机发送数据给另一台主机时,发送方除了要发送数据外还要把自己的 IP地址和端口号 发送给接收方,所以接收方能给发送方回数据。所以说通信是双方的。
4.TCP协议简介
- TCP(Transmission Control Protocol 传输控制协议),TCP协议是一种有连接、可靠、面向字节流的传输层通信协议。
- TCP协议是面向连接的,如果两台主机之间想要进行数据传输,那么必须要先建立连接,当连接建立成功后才能进行数据传输。
- TCP协议是可靠的,因为TCP协议注重丢包率, TCP协议花费大量开销解决数据在传输过程中出现的丢包、乱序等问题,保证不丢包。文件传输、电子邮件、网站访问一般用的就是TCP协议。
5.UDP协议简介
- UDP(User Datagram Protocol 用户数据报协议),UDP协议是一种无连接、不可靠、面向数据报的传输层通信协议。
- 使用UDP协议进行通信时无需建立连接,如果两台主机之间想要进行数据传输,那么直接将数据发送给对端主机就行了。
- UDP协议是不可靠的,因为UDP协议注重效率,没有处理在传输数据过程中小概率出现的丢包、乱序等情况。直播一般用的就是UDP协议。
6.网络字节序
6.0 大端字节序和小端字节序
- 大端字节序:是将数据的低位字节放到高地址处,高位字节放到低地址处。
(大端低地址高字节:“大弟高”)
- 小端字节序,是将数据的低位字节放到低地址处,高位字节放到高地址处。
(小端低地址低字节:“小弟弟”)
6.1 是什么?
即网络通信中共同遵守的字节序,规定为 大端字节序(低字节,高地址)。
6.2 为什么?
不同计算机的 字节序不同,如果在网络通信时不加以规定,会出现发送方以大端模式发送数据,接收方以小端模式读取数据,导致通信失败的情况。
6.3 怎么定义?
TCP/IP协议规定,网络数据流应采用大端字节序,即低地址高字节。 不管这台主机是大端机还是小端机, 都会按照这个TCP/IP规定的网络字节序来发送/接收数据。如果当前发送主机是小端, 就需要先将数据转成大端再发送,否则直接发送。
6.4 网络字节序与主机字节序之间的转换函数
为使网络程序具有可移植性,使同样的C代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做网络字节序和主机字节序的转换
#include <arpa/inet.h>uint32_t htonl(uint32_t hostlong); //将主机字节序(h)转换为(to)网络字节序(n)要转化的数据是长整数(l)。uint16_t htons(uint16_t hostshort); uint32_t ntohl(uint32_t netlong); uint16_t ntohs(uint16_t netshort);
- 这些函数名很好记:h表示host,n表示network,l表示32位长整数,s表示16位短整数。所以htonl表示:将主机字节序(h)转换为(to)网络字节序(n)要转化的数据是长整数(l)。
- 如果主机是小端字节序,这些函数将参数做相应的大小端转换然后返回。
- 如果主机是大端字节序,这些 函数不做转换,将参数原封不动地返回。
二、socket
1.什么是socket(套接字)?
IP地址+端口号就是socket(套接字) ,用来标定某主机上的某进程。
2.为什么要有套接字?
有了套接字,不同主机的进程才能在网络中找到彼此,才能进行网络通信(进程间通信的前提是能互相看到彼此),所以说套接字是网络通信的基石。其次有了套接字,开发者才能开发出通用的网络通信接口,用户也能拿着套接字去使用这些接口。
3.套接字的主要类型
- 网络套接字:应用于跨主机网络通信,也支持本地通信,主要有两种:
a.流套接字:用于读取TCP协议的数据。
b.数据报套接字:用于读取UDP协议的数据。- unix域间套接字:只能进行本地通信。
- 原始套接字(SOCK_RAW):可以从应用层直接绕开传输层,直接去访问底层协议,所以原始套接字可以读写内核没有处理的IP数据包,而流套接字只能读取TCP协议的数据,数据报套接字只能读取UDP协议的数据。因此,如果要访问其他协议发送的数据必须使用原始套接字。
拓】网络套接字
- 流套接字(SOCK_STREAM)流套接字用于提供面向连接、可靠的数据传输服务。该服务将保证数据能够实现无差错、无重复送,并按顺序接收。流套接字之所以能够实现可靠的数据服务,原因TCP协议。流套接字只能读取TCP协议的数据。
- 数据报套接字(SOCK_DGRAM)数据报套接字提供一种无连接的服务。该服务并不能保证数据传输的可靠性,数据有可能在传输过程中丢失或出现数据重复,且无法保证顺序地接收到数据。数据报套接字使用UDP( User DatagramProtocol)协议进行数据的传输。由于数据报套接字不能保证数据传输的可靠性,对于有可能出现的数据丢失情况,需要在程序中做相应的处理。数据报套接字只能读取UDP协议的数据。
拓】功能强大的套接字
套接字是非常强大的,虽然现在主要用于网络通信,但其实套接字可以用于几乎任何类型的进程间通信:本地通信、各种类型的网络通信等。
三、socket API
1.socket API是什么?
是提供给程序员(应用层)做网络开发所用的接口,用来实现不同主机中进程的通信。
Socket API(套接字编程接口)实际是 传输层 提供给 应用层 的编程接口,用来实现不同主机中进程的通信:传输层在网络层的基础上提供进程到进程问的逻辑通道,而应用层的进程则利用传输层向另一台主机的某一进程通信。Socket就是应用层与传输层之间的桥梁,使用Socket编程可以开发客户端和服务端应用程序,从而通过网络实现在全球范围内通信。
2.为什么要有Socket API?
socket(套接字)只是网络通信的前提,只有开发出一套通用的网络接口才能实现不同主机中进程的通信。Linux下的这套接口就是Socket API(套接字编程接口)。
3.Socket编程常见API
3.1 socket()
int socket(int domain, int type, int protocol);
//创建socket_fd(套接字 文件描述符),用于TCP/UDP网络程序中的客户端 + 服务器![]()
3.2 bind()
//让 socket_fd和sockaddr_in绑定, 用于 TCP/UDP 网络程序中的 服务器。![]()
3.3 listen ()
//开始监听socket,用于 TCP 网络程序中的 服务器
3.4 accept()
//接收请求,用于 TCP 网络程序中的 服务器
3.5 connect ()
//建立连接,用于 TCP 网络程序中的 服务器
四、sockaddr
1. 是什么?
struct sockaddr(套接字地址结构体)是Linux用来保存套接字和套接字类型的结构体。
2. 为什么?
使用Socket API要需要传入套接字,Linux选择用struct sockaddr保存套接字和套接字类型。在Linux下使用Socket API要传入struct sockaddr*。
3. sockaddr的分类
Linux中只设置了一套Socket API(套接字编程接口),但是有不同类型的套接字(用于IPv4的套接字、用于IPv6的、用于本地通信的) ,所以使用struct sockaddr、struct sockaddr_in 、struct sockaddr_un来区分不同类型的套接字:
sockaddr、sockaddr_in 和 sockaddr_un结构体头部的16个比特位(2字节)都是一样的,这16位是地址类型用来区分套接字的类型的,根据套接字的类型(IPv4、IPv6……),分别定义为常数AF_INET、AF_INET6……
Socket API都用struct sockaddr *类型传参,将 sockaddr_in 或 sockaddr_un强制类型转换为sockaddr,才能被Socket API识别。对于传进来的参数 sockaddr ,函数通过前两个字节,进行判断是网络通信还是本地通信,知道这个结果后再强制类型转换回 sockaddr_in 和 sockaddr_un结构体。这样的好处是程序的通用性, 可以接收IPv4, IPv6, 以及UNIX Domain Socket各种类型的sockaddr结构体指针做为参数。
4.Linux中sockaddr的声明
- struct sockaddr(在头文件:<sys/socket.h>中)
- struct sockaddr_in (在头文件:<netinet/in.h>中)
- struct sockaddr_un (在头文件:<sys/un.h>中)
5.创建并填充struct sockaddr_in
4.0 导入结构体定义所在的头文件。
#include <netinet/in.h>
struct sockaddr_in ,定义在头文件:<netinet/in.h>中。
4.1 定义struct sockaddr_in变量。
struct sockaddr_in local;
- struct sockaddr_in:用来定义Ipv4和Ipv6的套接字结构体,用于网络通信。
- struct sockaddr_un :用来定义UNIX_Domain_Socket(Unix域套接字:用于同一台主机上进程间通信)。用于本地通信。
4.2 初始化结构体
bzero(&local, sizeof(local));
使用bzero() 或 memset()初始化结构体的内存空间为0 。
4.3 设置地址类型
local.sin_family = AF_INET;
4.4 设置端口号 (保存端口号的变量为:port,是一个2字节16位的整数)
local.sin_port = htons(port);
端口号要被对方获取,也是网络数据的一部分,所以要考虑大小端问题,使用htons函数将主机字节序转为网络字节序。
4.5 设置IP地址 (保存IP地址的变量为:ip,是一个点分十进制字符串)
local.sin_addr.s_addr = inet_addr(ip);
inet_addr()的作用:
1.将点分十进制字符串风格的IP地址 -> 4字节整数
2.ip地址也要考虑大小端:将4字节整数 -> 网络序列
6.使用sockaddr传参
Socket API只接受struct sockaddr *类型传参,所以将 sockaddr_in、 sockaddr_un强制类型转换为sockaddr,才能被Socket API识别。
对于传进来的参数 sockaddr ,函数通过前两个字节,进行判断是网络通信还是本地通信,知道这个结果后再强制类型转换回 sockaddr_in 和 sockaddr_un结构体。这样的好处是程序的通用性, 可以接收IPv4, IPv6, 以及UNIX Domain Socket各种类型的sockaddr结构体指针做为参数。
相关文章:

Linux网络编程 socket编程篇(一) socket编程基础
目录 一、预备知识 1.IP地址 2.端口号 3.网络通信 4.TCP协议简介 5.UDP协议简介 6.网络字节序 二、socket 1.什么是socket(套接字)? 2.为什么要有套接字? 3.套接字的主要类型 拓】网络套接字 三、socket API 1.socket API是什么? 2.为什么…...

【二】SPI IP核的使用
【一】SPI IP核使用:传送门 基于qsys通过spi外部总线协议对sd卡进行读写操作 一、实验平台与实验的目的: 正点原子开拓者、芯片型号:EP4CE10F17C8;还需要一张sd卡。 该实验主要是利用SPI IP核驱动SD卡来实现读写实验&am…...

面试热题(二叉树的锯齿形层次遍历)
给你二叉树的根节点 root ,返回其节点值的 锯齿形层序遍历 。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行) 输入:root [3,9,20,null,null,15,7] 输出:[[3…...

JVM—内存管理(运行时数据区)、垃圾回收
背景介绍 当JVM类加载器加载完字节码文件之后,会交给执行引擎执行,在执行的过程中会有一块JVM内存区域来存放程序运行过程中的数据,也就是我们图中放的运行时数据区,那这一块运行时数据区究竟帮我们做了哪些工作?我们…...

一百五十一、Kettle——Linux上安装的kettle8.2开启carte服务
一、目的 kettle8.2在Linux上安装好可以启动界面、并且可以连接MySQL、Hive、ClickHouse等数据库后,准备在Linux上启动kettle的carte服务 二、实施步骤 (一)carte服务文件路径 kettle的Linux运行的carte服务文件是carte.sh (二…...

19. python从入门到精通——Web编程
HTTP协议 HTTP协议的常用方法 方法 描述 GET 请求指定的页面信息,并返回实体主体。 POST 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。 …...
PostMan 教程
安装https://www.cnblogs.com/mafly/p/postman.html Postman 使用方法详解https://blog.csdn.net/fxbin123/article/details/80428216 postman进行http接口测试https://blog.csdn.net/five3/article/details/53021084 postman的使用方法详解!最全面的教程https:/…...
Http常见状态码
一、状态码大类 状态码分类说明1xx响应中——临时状态码,表示请求已经接受,告诉客户端应该继续请求或者如果它已经完成则忽略它2xx成功——表示请求已经被成功接收,处理已完成3xx重定向——重定向到其它地方:它让客户端再发起一个…...

C语言之位运算
一、什么是位运算 所谓位运算是指进行二进制位的运算 在系统软件中,常要处理二进位的问题 例如,将一个存储单元中的各二进位左移或右移一位,两个数按位相加等 二、位运算符和位运算 1、按位与 运算符(&) 参加运算的两个数据ÿ…...

c语言进阶部分详解(数据在内存中的存储)
大家好,今天要进行梳理的内容是数据在内存中的存储相关内容。 在C语言中,数据在内存中的存储是一个非常重要的概念。了解数据在内存中的存储方式可以帮助我们更好地理解程序的执行过程,优化内存使用,提高程序的性能。 目录 一.数…...

VIOOVI的ECRS工时分析软件分析:SOP的核心和特征是什么?
制定SOP的主要目的是为企业做技术储备、提供企业的工作效率、防止同样的错误反复出现、让员工作业有标准化的行为准则。以规定的成本、规定的工作时间,生产质量均匀、符合规范的产品。为了能够达到上述要求,如果制造现场的操作混乱,比如制作工…...

无涯教程-Perl - lock函数
描述 此函数将咨询锁放在共享变量或THING中包含的引用对象上,直到该锁超出范围。 lock()是一个"弱关键字":这意味着,如果您在调用该函数之前已通过该名称定义了该函数,则将改为调用该函数。 语法 以下是此函数的简单语法- lock THING返回值 此函数不返回任何值…...
SpringBoot案例-部门管理-前后端联调
前后端联调 教学资料中提供了“前端工程”,将其解压即可使用nginx,启动nginx后,访问:http://localhost:90 小结 开发流程 明确需求、阅读接口文档、思路分析、接口开发(遵循接口文档)接口调试 postman测…...

每天一道leetcode:139. 单词拆分(动态规划中等)
今日份题目: 给你一个字符串 s 和一个字符串列表 wordDict 作为字典。请你判断是否可以利用字典中出现的单词拼接出 s 。 注意:不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。 示例1 输入: s "leetcode", …...
【C++】友元(含内部类)
一、友元是什么 我把你添加为我的友元,那么你可以访问我的成员。特别注意:它是单向的。即,我把你添加为我的友元,我却不能访问你的成员,除非你把我添加为你的友元。 以下代码可以让你粗略了解友元的使用。 #includ…...

SQL | 检索数据
1-检索数据 1.1-检索单个列 SELECT prod_name FROM Products; 上述SELECT语句从Products表中检索一个名为prod_name的列。 所要查找的列在select后面,from关键字指出从那个表查询数据。 输出如下: prod_name8 inch teddy bear12 inch teddy bear18…...
typeScript 之 运算符
工具: PlayGround 算术运算符 运算符描述加-减*乘/除%取模(求余)自增–自减 注意和--,实例: let value 0; console.log(value); //0, 先显示再增加后为1 console.log(value); //2,先增加后为2再显示关系运算符 运算符描述 …...

BGP实验
题目 IP地址配置 172.16.X.0/24为模拟用户环回接口接口 172.16.7.X/32为BGP邻居关系建立的环回接口 R1: R2: R3: R4: R5: R6: R7: R8: BGP邻居关系建立、宣告和反射器、联邦配置 R…...

pytest fixture 常用参数
fixture 常用的参数 参数一:autouse,作用:自动运行,无需调用 举例一:我们在类中定义一个function 范围的fixture; 设置它自动执行autouseTrue,那么我们看下它执行结果 输出: 说明:…...

vue项目里面有多个模块的服务,前端处理url转发
先看下vue的代理配置里面: 现在是在 /pca 基础上增加了 2个模块的服务: /dca、 /api 现在服务器的nginx 没有在/pca 服务里面做转发接受 /dca、 /api的服务,所以需要前端自己去配置每个服务模块对应的 URL 先拿登录的api 做示例吧: 先定义…...

使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...

【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...

算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...

C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
人工智能--安全大模型训练计划:基于Fine-tuning + LLM Agent
安全大模型训练计划:基于Fine-tuning LLM Agent 1. 构建高质量安全数据集 目标:为安全大模型创建高质量、去偏、符合伦理的训练数据集,涵盖安全相关任务(如有害内容检测、隐私保护、道德推理等)。 1.1 数据收集 描…...

HubSpot推出与ChatGPT的深度集成引发兴奋与担忧
上周三,HubSpot宣布已构建与ChatGPT的深度集成,这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋,但同时也存在一些关于数据安全的担忧。 许多网络声音声称,这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...

医疗AI模型可解释性编程研究:基于SHAP、LIME与Anchor
1 医疗树模型与可解释人工智能基础 医疗领域的人工智能应用正迅速从理论研究转向临床实践,在这一过程中,模型可解释性已成为确保AI系统被医疗专业人员接受和信任的关键因素。基于树模型的集成算法(如RandomForest、XGBoost、LightGBM)因其卓越的预测性能和相对良好的解释性…...

小智AI+MCP
什么是小智AI和MCP 如果还不清楚的先看往期文章 手搓小智AI聊天机器人 MCP 深度解析:AI 的USB接口 如何使用小智MCP 1.刷支持mcp的小智固件 2.下载官方MCP的示例代码 Github:https://github.com/78/mcp-calculator 安这个步骤执行 其中MCP_ENDPOI…...
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__ is not explicitly defined.
这个警告表明您在使用Vue的esm-bundler构建版本时,未明确定义编译时特性标志。以下是详细解释和解决方案: 问题原因: 该标志是Vue 3.4引入的编译时特性标志,用于控制生产环境下SSR水合不匹配错误的详细报告1使用esm-bundler…...
el-amap-bezier-curve运用及线弧度设置
文章目录 简介示例线弧度属性主要弧度相关属性其他相关样式属性完整示例链接简介 el-amap-bezier-curve 是 Vue-Amap 组件库中的一个组件,用于在 高德地图 上绘制贝塞尔曲线。 基本用法属性path定义曲线的路径,可以是多个弧线段的组合。stroke-weight线条的宽度。stroke…...