当前位置: 首页 > 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…...

vscode里如何用git

打开vs终端执行如下&#xff1a; 1 初始化 Git 仓库&#xff08;如果尚未初始化&#xff09; git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查

在对接支付宝API的时候&#xff0c;遇到了一些问题&#xff0c;记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

C++中string流知识详解和示例

一、概览与类体系 C 提供三种基于内存字符串的流&#xff0c;定义在 <sstream> 中&#xff1a; std::istringstream&#xff1a;输入流&#xff0c;从已有字符串中读取并解析。std::ostringstream&#xff1a;输出流&#xff0c;向内部缓冲区写入内容&#xff0c;最终取…...

Device Mapper 机制

Device Mapper 机制详解 Device Mapper&#xff08;简称 DM&#xff09;是 Linux 内核中的一套通用块设备映射框架&#xff0c;为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程&#xff0c;并配以详细的…...

html-<abbr> 缩写或首字母缩略词

定义与作用 <abbr> 标签用于表示缩写或首字母缩略词&#xff0c;它可以帮助用户更好地理解缩写的含义&#xff0c;尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时&#xff0c;会显示一个提示框。 示例&#x…...

网站指纹识别

网站指纹识别 网站的最基本组成&#xff1a;服务器&#xff08;操作系统&#xff09;、中间件&#xff08;web容器&#xff09;、脚本语言、数据厍 为什么要了解这些&#xff1f;举个例子&#xff1a;发现了一个文件读取漏洞&#xff0c;我们需要读/etc/passwd&#xff0c;如…...

Caliper 负载(Workload)详细解析

Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...

xmind转换为markdown

文章目录 解锁思维导图新姿势&#xff1a;将XMind转为结构化Markdown 一、认识Xmind结构二、核心转换流程详解1.解压XMind文件&#xff08;ZIP处理&#xff09;2.解析JSON数据结构3&#xff1a;递归转换树形结构4&#xff1a;Markdown层级生成逻辑 三、完整代码 解锁思维导图新…...