当前位置: 首页 > news >正文

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)

相关文章:

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

文章目录 网络字节序socket编程socket 常见APIsockaddr结构 UDP编程创建socket绑定socketsendto发送数据recvform接收数据关闭socket TCP编程创建socket绑定socketlisten监听套接字accept服务端接收连接套接字connect客户端连接套接字send发送数据recv接收数据关闭socket 工具n…...

Data Structure, Algorithm,and Applications in C++

在学习这本书进阶内容之前&#xff0c;我们可以跟着它的第一章部分再巩固和复习。本书由Sartaj Sahni撰写&#xff0c;由王立柱和刘志红翻译。全书通俗易懂&#xff0c;内容丰富&#xff0c;是巩固C内容的不二选择。希望本文对各位有所帮助。 目录 1.函数与参数 1.1.传值参数…...

Apipost使用教程

Apipost是一款集API调试、生成文档、Mock、测试于一体的协同工具。单个工具可以同时满足接口测试、生成/分享文档、Mock、流程测试等功能&#xff0c;还有超实用的多人多角色间实时协作的功能。将前端、后端、测试三种角色串联起来&#xff0c;从而实现工作流程无缝衔接、提高研…...

如何使用Python进行服务器管理和自动化操作?

使用Python进行服务器管理和自动化操作可以极大地简化和提高日常管理任务的效率。下面是一些常见的方法和工具&#xff1a; SSH库&#xff1a;使用Python的paramiko库可以通过SSH协议连接到服务器&#xff0c;执行命令、上传文件和下载文件等操作。 例如&#xff0c;使用para…...

Kafka-partition和消费者的关系

Kafka-partition 目录概述需求&#xff1a; 设计思路实现思路分析1.Kafka-partition2.消费者数量小于分区数量3. 拓展实现 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a…...

使用克拉默法则进行三点定圆(二维)

目录 1.二维圆2.python代码3.计算结果 本文由CSDN点云侠原创&#xff0c;爬虫网站请自重。 1.二维圆 已知不共线的三个点&#xff0c;设其坐标为 ( x 1 , y 1 ) (x_1,y_1) (x1​,y1​)、 ( x 2 , y 2 ) (x_2,y_2) (x2​,y2​)、 ( x 3 , y 3 ) (x_3,y_3) (x3​,y3​)&#xf…...

【Java】Java多线程编程基础

文章目录 1. 进程与线程1.1 进程与线程的基本认识1.1.1 进程&#xff08;Process&#xff09;1.1.2 线程&#xff08;Thread&#xff09; 1.2 为什么会有线程1.2.1 以看视频为例 2. 多线程实现2.1 Thread类实现多线程2.2 Runnable接口实现多线程2.3 Callable接口实现多线程2.3 …...

FFmpeg-4.2.4的去logo源码分析

1.源码 libavfilter/vf_delogo.c 2.源码分析 /** 去logo算法, 函数的参数解释如下: w: 输入图像的宽度 h: 输入图像的高度 logo_x: 标志区域左上角的x坐标 logo_y: 标志区域左上角的y坐标 logo_w: 标志的宽度 logo_h: 标志的高度 band: 处理区域周围的带宽大小 show: 是否在…...

深度学习(一)

目录 一、特征工程的作用 二、深度学习的应用 三、得分函数 四、损失函数 五、前向传播 六、反向传播 一、特征工程的作用 数据特征决定了模型的上限预处理和特征提取是最核心的算法与参数选择决定了如何逼近这个上限 二、深度学习的应用 无人驾驶人脸识别分辨率重构 深…...

Stream API将对象中的某一字段取出转换为list或数组

List<DevicePartMaintain> devicePartMaintainList devicePartMaintainMapper.selectDevicePartMaintainByMitId(mitId);所有id转换为List 要使用Stream流获取devicePartMaintainList中所有的id&#xff0c;您可以使用stream()方法将列表转换为流&#xff0c;然后使用…...

什么是Java中的JVM(Java虚拟机)?

JVM&#xff08;Java虚拟机&#xff09;是Java平台的核心组件之一&#xff0c;是一个用于执行Java字节码的虚拟计算机。Java源代码经过编译器编译&#xff0c;生成字节码文件&#xff08;.class文件&#xff09;&#xff0c;然后由JVM来解释和执行这些字节码。JVM负责将字节码翻…...

springboot + redis + 注解 + 拦截器 实现接口幂等性校验

一、概念 幂等是一个数学与计算机学概念&#xff0c;在数学中某一元运算为幂等时&#xff0c;其作用在任一元素两次后会和其作用一次的结果相同。在计算机中编程中&#xff0c;一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。 幂等函数或幂等方法是…...

PLC编程:关键在于模拟操作流程和实现控制

PLC编程的核心是通过程序描述流程&#xff0c;完成控制过程。因此&#xff0c;掌握PLC编程语言和基本功能实现是必要的。 PLC语言主要分为梯形图、语句和功能图。梯形图适合基本逻辑描述&#xff0c;语句表用于数据处理&#xff0c;相对较难理解。步进式功能图的状态函数描述很…...

List的各种排序

目录 Collections.sort对list进行排序 对象中某个属性进行排序 通过比较器进行比较 JAVA8特性Stream流进行排序 Stream升降序组合使用 Collections.sort对list进行排序 public static void main(String[] args) {List<Integer> list new ArrayList<>();list…...

在自定义数据集上微调Alpaca和LLaMA

本文将介绍使用LoRa在本地机器上微调Alpaca和LLaMA&#xff0c;我们将介绍在特定数据集上对Alpaca LoRa进行微调的整个过程&#xff0c;本文将涵盖数据处理、模型训练和使用流行的自然语言处理库(如Transformers和hugs Face)进行评估。此外还将介绍如何使用grado应用程序部署和…...

Python 实现接口类的两种方式+邮件提醒+动态导入模块+反射(参考Django中间件源码)

实现抽象类的两种方式 方式一 from abc import ABCMeta from abc import abstractmethodclass BaseMessage(metaclassABCMeta):abstractmethoddef send(self,subject,body,to,name):pass 方式二 class BaseMessage(object):def send(self, subject, body, to, name):raise …...

Solr原理剖析

一、简介 Solr是一个高性能、基于Lucene的全文检索服务器。Solr对Lucene进行了扩展&#xff0c;提供了比Lucene更为丰富的查询语言&#xff0c;并实现了强大的全文检索功能、高亮显示、动态集群&#xff0c;具有高度的可扩展性。同时从Solr 4.0版本开始&#xff0c;支持SolrCl…...

解决 “无法将 ‘npm‘ 项识别为 cmdlet、函数、脚本文件或可运行程序的名称“ 错误的方法

系列文章目录 文章目录 系列文章目录前言一、错误原因&#xff1a;二、解决方法&#xff1a;三、注意事项&#xff1a;总结 前言 在使用 npm 进行前端项目开发时&#xff0c;有时会遇到错误信息 “无法将 ‘npm’ 项识别为 cmdlet、函数、脚本文件或可运行程序的名称”&#x…...

Python 电商API 开发最佳实践

一、简介 当你打卡了一家北京最具有地中海特色的餐厅&#xff0c;当我们在餐厅点餐时&#xff0c;服务员会给我们一份菜单&#xff0c;菜单上列出了所有可供选择的菜品和饮料。我们可以在菜单上选择我们想要的食物和饮料&#xff0c;然后告诉服务员我们的选择。服务员会根据我…...

JAVA基础-集合(List与Map)

目录 引言 一&#xff0c;Collection集合 1.1,List接口 1.1.1&#xff0c;ArrayList 1.1.1.1&#xff0c;ArrayList的add&#xff08;&#xff09;添加方法 1.1.1.2&#xff0c;ArrayList的remove&#xff08;&#xff09;删除方法 1.1.1.3&#xff0c;ArrayList的contai…...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题&#xff1a; 下面创建一个简单的Flask RESTful API示例。首先&#xff0c;我们需要创建环境&#xff0c;安装必要的依赖&#xff0c;然后…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中&#xff0c;Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染&#xff08;即CPU被阻塞&#xff09;&#xff0c;这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&…...

linux arm系统烧录

1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 &#xff08;忘了有没有这步了 估计有&#xff09; 刷机程序 和 镜像 就不提供了。要刷的时…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放

简介 前面两期文章我们介绍了I2S的读取和写入&#xff0c;一个是通过INMP441麦克风模块采集音频&#xff0c;一个是通过PCM5102A模块播放音频&#xff0c;那如果我们将两者结合起来&#xff0c;将麦克风采集到的音频通过PCM5102A播放&#xff0c;是不是就可以做一个扩音器了呢…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统

目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索&#xff08;基于物理空间 广播范围&#xff09;2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲

文章目录 前言第一部分&#xff1a;体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分&#xff1a;体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...