09.计算机网络——套接字编程

文章目录

  • 网络字节序
  • socket编程
    • socket 常见API
    • sockaddr结构
  • UDP编程
    • 创建socket
    • 绑定socket
    • sendto发送数据
    • recvform接收数据
    • 关闭socket
  • TCP编程
    • 创建socket
    • 绑定socket
    • listen监听套接字
    • accept服务端接收连接套接字
    • connect客户端连接套接字
    • send发送数据
    • recv接收数据
    • 关闭socket
  • 工具
    • netstat
    • telnet
    • 地址转换函数
  • socket编程注意细节
  • 代码案例


网络字节序

​ 内存中的多字节数据相对于内存地址有大端和小端之分,磁盘文件中的多字节数据相对于文件中的偏移地址也有大端小端之分,网络数据流同样有大端小端之分。
​ TCP/IP协议规定,网络数据流应采用大端字节序,即低地址高字节。不管这台主机是大端机还是小端机, 都会按照这个TCP/IP规定的网络字节序来发送/接收数据。为使网络程序具有可移植性,使同样的C代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做网络字节序和主机字节序的转换。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oWm0b8Ym-1689856659297)(C:\Users\11794\AppData\Roaming\Typora\typora-user-images\image-20230720171128069.png)]

  • h表示host,n表示network,l表示32位长整数,s表示16位短整数。

  • htonl表示将32位的长整数从主机字节序转换为网络字节序。

  • ntohl表示将32位的长整数从网络字节序转换为主机字节序。


socket编程

​ socket套接字通常指的是封装了ip和port的结构体,其是网络编程中的一种通信机制,支持TCP/IP的网络通信的基本操作单元,简单的说就是通信的两方的一种约定,用套接字中的相关函数来完成通信过程。


socket 常见API

// 创建 socket 文件描述符 (TCP/UDP, 客户端 + 服务器)
int socket(int domain, int type, int protocol);// 绑定端口号 (TCP/UDP, 服务器)
int bind(int socket, const struct sockaddr *address,socklen_t address_len);// 开始监听socket (TCP, 服务器)
int listen(int socket, int backlog);// 接收请求 (TCP, 服务器)
int accept(int socket, struct sockaddr* address,socklen_t* address_len);// 建立连接 (TCP, 客户端)
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

sockaddr结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Jm27OicV-1689856659297)(C:\Users\11794\AppData\Roaming\Typora\typora-user-images\image-20230720182915989.png)]

套接字分类:

  1. 域间套接字 —— 本地通信
  2. 原始套接字 —— 允许绕过传输层,直接跟底层打交道,主要用来写一些工具。
  3. 网络套接字 —— 网络通信

​ 理论上是三种应用场景,对应的应该是三套接口,但是Linux设计套接字的时候不想设计过多的接口,所以Linux将所有的接口进行了统一,只使用sockaddr结构体来描述这三种场景。 但是真正在基于IPv4编程时, 使用的数据结构是sockaddr_in; 这个结构里主要有三部分信息: 地址类型, 端口号, IP地址。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e69gOlTy-1689856659298)(C:\Users\11794\AppData\Roaming\Typora\typora-user-images\image-20230720183050113.png)]


UDP编程

创建socket

#include <sys/types.h>
#include <sys/socket.h>
// 创建 socket 文件描述符 (TCP/UDP, 客户端 + 服务器)
int socket(int domain, int type, int protocol);
//参数
domain:指定网络层的协议AF_INT: 使用ipv4版本的ip协议AF_INT6:使用ipv6版本的ip协议AF_UNIX:本地通信
type: 指定套接字的类型SOCK_DGRAM :使用UDP数据报套接字SOCK_STREAM:使用TCP字节流套接字
protocol:指定使用的协议0:使用套接字类型对应的默认协议

绑定socket

int bind(int socket, const struct sockaddr* address,socklen_t address_len);*
//参数
sockfd:		socket函数返回的套接字描述符
addr:		地址信息结构体成员,struct sockaddr 是一个通用地址信息结构
address_len:地址信息结构的长度

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:	目标主机地址信息结构体的长度
//返回值
成功返回发送的字节数量,失败返回-1

recvform接收数据

ssize_t recvfrom(int sockfd, void* buf, size_t len, int flags,struct sockaddr* src_addr, socklen_t* addrlen);
//参数
sockfd:		套接字描述符
buf:		将数据接收到buf当中
len:		buf的最大接收能力
flags:		0-阻塞接收
src_addr:	数据来源的主机地址信息结构体  
addrlen:	输入输出型参数
//返回值
成功则返回实际接收到的字符数,失败返回-1,错误原因会存于errno中

关闭socket

close(int sockfd);
//sockfd:		套接字描述符

TCP编程

创建socket

#include <sys/types.h>
#include <sys/socket.h>
// 创建 socket 文件描述符 (TCP/UDP, 客户端 + 服务器)
int socket(int domain, int type, int protocol);
//参数
domain:指定网络层的协议AF_INT: 使用ipv4版本的ip协议AF_INT6:使用ipv6版本的ip协议AF_UNIX:本地通信
type: 指定套接字的类型SOCK_DGRAM :使用UDP数据报套接字SOCK_STREAM:使用TCP字节流套接字
protocol:指定使用的协议0:使用套接字类型对应的默认协议
//返回值:
socket()打开一个网络通讯端口,如果成功的话,就像open()一样返回一个文件描述符,程序可以像读写文件一样用read/write在网络上收发数据;调用出错则返回-1

绑定socket

int bind(int socket, const struct sockaddr* address,socklen_t address_len);*
//参数
sockfd:		socket函数返回的套接字描述符
addr:		地址信息结构体成员,struct sockaddr 是一个通用地址信息结构
address_len:地址信息结构的长度

listen监听套接字

//listen()声明sockfd处于监听状态
int listen(int sockfd, int backlog);
//参数
sockfd:	套接字描述符
backlog:已完成连接队列的大小
//返回值:成功:0失败:-1

当客户端和服务端进行三次握手的时候会存在两种状态:连接还未建立和连接已建立,此时操作系统内核中就会存在两个队列:未完成连接队列和已完成连接队列。当完成三次握手后会由未完成连接队列放到已完成连接队列,而backlog就是已完成连接队列的大小,backlog影响了服务端并发接收连接的能力。

accept服务端接收连接套接字

//从已经完成连接队列中获取已经完成三次握手的连接,没有连接时,调用accept会阻塞等待。
int accept(int sockfd, struct sockaddr* addr, socklen_t * addrlen);
//参数
sockfd:套接字描述符(listen_sockfd)
addr:输出型参数,保存客户端地址信息结构(客户端IP,客户端的端口)
addrlen:输入输出参数,传入缓冲区的大小,传出客户端地址信息结构的长度
//返回值成功:返回新连接的套接字描述符失败:返回-1

三次握手的时候是对listen_sockfd进行操作,当调用accept()会在Tcp服务端内部创建一个新的套接字new_sockfd,三次握手之后的数据收发都是多new_sockfd进行操作。


connect客户端连接套接字

//客户端需要调用connect()连接服务器
int connect(int sockfd, const struct sockaddr * addr,socklen_t addrlen);
//参数
sockfd:套接字描述符(listen_sockfd)
addr:服务端地址信息结构(服务端IP,服务端的端口)
addrlen:服务端地址信息结构的长度
//返回值成功:返回0小于0,连接失败

send发送数据

ssize_t send(int sockfd, const void * buf, size_t len, int flags);//参数
sockfd:套接字描述符(new_sockfd)
buf:待要发送的数据
len:发送数据的长度
flags:0:阻塞发送MSG_OOB:发送带外数据,在紧急情况下所产生的数据,会越过前面进行排队的数据优先进行发送。//返回值大于0:返回发送的字节数量-1:发送失败

recv接收数据

ssize_t recv(int sockfd, void * buf, size_t len, int flags);//参数
sockfd:套接字描述符(new_sockfd)
buf:将接收的数据放到buf
len:buf的最大接收能力
flags:0:阻塞发送;如果客户端没有发送数据,调用recv会阻塞//返回值大于0:正常接收了多少字节数据等于0:对端将连接关闭了小于0:接受失败

关闭socket

close(int sockfd);
//sockfd:		套接字描述符

工具

netstat

netstat -anp | grep [端口号]
  • 查看端口的使用情况

telnet

  • 进入cmd,使用telnet模仿TCP三次握手建立连接,在cmd窗口输入 “tenlet + 公网IP + 端口号” 即可模拟测试

地址转换函数

sockaddr_in中的成员struct in_addr sin_addr表示32位 的IP 地址,但是我们通常用点分十进制的字符串表示IP 地址,以下函数可以在字符串表示 和in_addr表示之间转换

字符串转in_addr的函数:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Oo44FIpo-1689856659298)(C:\Users\11794\AppData\Roaming\Typora\typora-user-images\image-20230720195247336.png)]

in_addr转字符串的函数:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MIr8eH4R-1689856659298)(C:\Users\11794\AppData\Roaming\Typora\typora-user-images\image-20230720195258821.png)]

inet_ntoa函数把这个返回结果放到了静态存储区,这个时候不需要我们手动进行释放。

socket编程注意细节

  • 客户端没有必要调用bind()固定一个端口号,否则如果在同一台机器上启动多个客户端,就会出现端口号被占用导致不能正确建立连接。
  • 服务器也不是必须调用bind(),但如果服务器不调用bind(), 内核会自动给服务器分配监听端口, 每次启动服务器时端口号都不一样,客户端要连接服务器就会遇到麻烦。
  • 多进程的客户端代码和单进程是一样的,父进程负责accept,子进程负责数据的接收和发送,若子进程一直不退出,则父进程一直在等待,永远无法接收新连接,可以使用自定义信号处理方式将SIGCHLD信号重新定义,当子进程退出发出SIGCHLD信号时,父进程则对子进程的资源进行回收。
  • 建立好了tcp连接之后,我们就可以把得到的fd当作文件描述符来使用,也可以使用read和 write函数进行读写

代码案例

UDP案例

UDP · 程序员Jared/Linux - 码云 - 开源中国 (gitee.com)

TCP案例

TCP · 程序员Jared/Linux - 码云 - 开源中国 (gitee.com)

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

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

相关文章

【flink】ColumnarRowData

列式存储 在调试flink读取parquet文件时&#xff0c;读出来的数据是ColumnarRowData&#xff0c;由于parquet是列式存储的文件格式&#xff0c;所以需要用一种列式存储的表示方式&#xff0c;ColumnarRowData就是用来表示列式存储的一行数据&#xff0c;它包含多个数组的数据结…

从电商指标洞察到运营归因,只需几句话?AI 数智助理准备好了!

Lily 是名入职不久的电商运营助理&#xff0c;最近她想要根据 2022 年的客单价情况&#xff0c;分析品牌 A 在不同电商渠道的用户行为和表现&#xff0c;并提供一些有价值的洞察和建议给客户。然而在向技术人员提报表需求后&#xff0c;技术人员以需求排满为借口拒绝了。 Lily …

5分钟,结合 LangChain 搭建自己的生成式智能问答系统

伴随大语言模型&#xff08;LLM&#xff0c;Large Language Model&#xff09;的涌现&#xff0c;人们发现生成式人工智能在非常多领域具有重要意义&#xff0c;如图像生成&#xff0c;书写文稿&#xff0c;信息搜索等。随着 LLM 场景的多样化&#xff0c;大家希望 LLM 能在垂直…

记一次容器环境下出现 Address not available

作者&#xff1a;郑明泉、余凯 困惑的源地址 pod 创建后一段时间一直是正常运行&#xff0c;突然有一天发现没有新的连接创建了&#xff0c;业务上是通过 pod A 访问 svc B 的 svc name 的方式&#xff0c;进入 pod 手动去 wget 一下&#xff0c;发现报错了 Address not avai…

jar 更新 jar包内的 class,以及如何修改class

一、提取Jar 内文件 #提取jar内的配置文件jar -xvf a.jar META-INF\plugin.xml-已解压: META-INF/plugin.xml#提取jar内的class文件&#xff0c; 提示&#xff1a;反编译为java文件&#xff0c;修改后再使用javac xxx.java编译为class&#xff0c;jar -xvf a.jar io.config.**…

单例模式类设计|什么是饿汉模式和懒汉模式

前言 那么这里博主先安利一些干货满满的专栏了&#xff01; 首先是博主的高质量博客的汇总&#xff0c;这个专栏里面的博客&#xff0c;都是博主最最用心写的一部分&#xff0c;干货满满&#xff0c;希望对大家有帮助。 高质量干货博客汇总https://blog.csdn.net/yu_cblog/c…

在Vue-Element中引入jQuery的方法

一、在终端窗口执行安装命令 npm install jquery --save执行完后&#xff0c;npm会自动在package.json中加上jquery 二、在main.js中引入&#xff08;或者在需要使用的页面中引入即可&#xff09; import $ from jquery三、使用jquery

【Ansible 自动化配置管理实践】01、Ansible 快速入门

目录 一、Ansible 快速入门 1.1 什么是 Ansible ​1.2 Ansible 主要功能 1.3 Ansible 的特点 1.4 Ansible 基础架构 二、Ansible 安装与配置 2.1 Ansible 安装 2.2 确认安装 三、Ansible 配置解读 3.1 Ansible 配置路径 3.2 Ansible 主配置文件 3.3 Ansi…

Spring系列一:spring的安装与使用

文章目录 &#x1f49e; 官方资料&#x1f34a;Spring5下载&#x1f34a;文档介绍 &#x1f49e;Spring5&#x1f34a;内容介绍&#x1f34a;重要概念 &#x1f49e;快速入门&#x1f34a;Spring操作演示&#x1f34a;类加载路径&#x1f34a;Debug配置&#x1f34a;Spring容器…

《Docker资源限制和调度策略:性能优化与资源管理,打造高效稳定的容器环境》

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

【Nodejs】Puppeteer\爬虫实践

puppeteer 文档:puppeteer.js中文文档|puppeteerjs中文网|puppeteer爬虫教程 Puppeteer本身依赖6.4以上的Node&#xff0c;但是为了异步超级好用的async/await&#xff0c;推荐使用7.6版本以上的Node。另外headless Chrome本身对服务器依赖的库的版本要求比较高&#xff0c;c…

高速数据采集专家-FMC140【产品手册】

FMC140是一款具有缓冲模拟输入的低功耗、12位、双通道&#xff08;5.2GSPS/通道&#xff09;、单通道10.4GSPS、射频采样ADC模块&#xff0c;该板卡为FMC标准&#xff0c;符合VITA57.1规范&#xff0c;该模块可以作为一个理想的IO单元耦合至FPGA前端&#xff0c;8通道的JESD204…

【jenkins】idea+jenkins+docker+dockerfile+compose流水线部署java应用

目录 整体架构 环境准备 安装docker以及docker-compose jenkins安裝 maven安装 portainer面板安装 sonarqube安装 在项目中增加dockerfile和compose.yml脚本 Dockerfile脚本内容 compose.yml脚本内容 jenkins安装必要插件 jenkins增加流水线任务 增加pipeline任务j…

iptables 防火墙

防火墙&#xff1a;隔离功能 部署在网络边缘或者主机边缘&#xff0c;在工作中&#xff0c;防火墙的主要作用&#xff0c;决定哪些数据可以被外网使用&#xff0c;以及哪些数据可以进入内网访问 主要工作在网络层 安全技术 1.入侵检测系统&#xff1a;检测出威胁&#xff0…

RISCV -3 RV32I/RV64I基本整型指令集

RISCV -3 RV32I/RV64I基本整型指令集 1 RV32I Base Integer Instruction Set1.1 Programmers’ Model for Base Integer ISA1.2 Base Instruction Formats1.3 Immediate Encoding Variants1.4 Integer Computational Instructions1.4.1 Integer Register-Immediate Instruction…

Windows 2012 R2 编辑ini文本遇到的编码问题

在编辑服务端配置文件时&#xff0c;发现对于ini文本文件&#xff1a; 需注意点一&#xff1a;如果另存为UTF-8保存的实际上格式是UTF-8-BOM编码格式&#xff1b; 但是两种格式是存在差异的&#xff1a; 因此造成在使用C#调用系统DLL读取文件时并未报错&#xff0c;但是当使用…

MySQL 数据库约束

目录 一、数据库约束 1、约束类型 二、NULL 约束 三、unique 约束 四、default 约束 五、primary key 约束 自增主键 六、foreign key 外键约束 七、check 约束 一、数据库约束 我们使用数据库来存储数据&#xff0c;一般是希望这里存储的数据是靠谱的&#xff0c;…

【梦辛工作室】IF判断优化、责任链模式 IfChain

大家好哇&#xff0c;我是梦辛工作室的灵&#xff0c;在最近的开发中&#xff0c;有许多需要判断的分支处理&#xff0c;且处理内容较多且复杂&#xff0c;代码就容易越写越复杂&#xff0c;导致后期无法继续更新跌打&#xff0c;然后基于这个环境&#xff0c;我用责任链模式写…

Stable Diffusion在各种显卡上的加速方式测试,最高可以提速211.2%

Stable Diffusion是一种基于扩散模型的图像生成技术&#xff0c;能够从文本生成高质量的图像&#xff0c;适用于CG&#xff0c;插图和高分辨率壁纸等领域。 但是它计算过程复杂&#xff0c;使得它的生成速度较慢。所以研究人员就创造了各种提高其速度的方式&#xff0c;比如Xf…

计算机视觉(二)图像特征提取

文章目录 颜色特征量化颜色直方图适用颜色空间&#xff1a;RGB、HSV等颜色空间操作 几何特征边缘 Edge边缘定义边缘提取 基于关键点的特征描述子引入几何特征&#xff1a;关键点几何特征&#xff1a;Harris角点FAST角点检测几何特征&#xff1a;斑点局部特征&#xff1a;SIFT预…