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

TCP网络编程(一)—— 服务器端模式和客户端模式

这篇文章将会编写基本的服务器网络程序,主要讲解服务器端和客户端代码的原理,至于网络名词很具体的概念,例如什么是TCP协议,不会过多涉及。

首先介绍一下TCP网络编程的两种模式:服务器端和客户端模式:

        首先说明一下:黑色线代表状态的转换,红色线表示的是数据的传输,read 和 write 之间的循环表示:例如读取完数据,进入写入的状态,写入完再进入读取的状态,一直循环,实现了服务器和客户端之间的通信。


首先来解释一下服务器端:

int socket(int domain, int type, int protocol)

socket() 表示创建一个套接字。套接字是网络通信的基本数据结构,用于定义通信协议(如 TCP 或 UDP)和地址族(如 IPv4 或 IPv6)。通过套接字,服务器和客户端可以在网络上传输数据,可以把套接字理解为一个编程接口,利用套接字实现程序和网络的连接,像是用户层和传输层(TCP)中间的一个抽象层,有了套接字才可以向网络发送数据。

传入的内容是(协议族,套接字类型,默认协议(通常为0))
返回:成功返回套接字描述符,失败返回-1 

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)

bind() 表示将套接字绑定到一个特定的地址和端口。绑定的地址和端口标识服务器,使客户端能够找到并连接到该服务。只有套接字还不够,我还要知道是哪个主机(IP)发送的,哪个应用程序(端口)发送的,端口可以理解为电脑通信的入口和出口。

传入的内容是:(套接字描述符,地址结构体的地址,地址结构体大小)
返回:成功返回0,失败返回-1。

int listen(int sockfd, int backlog)

listen() 表示将套接字转换为监听模式,并设置等待连接的队列长度。当多个客户端请求连接时,服务器会将这些请求加入队列,按顺序处理。

传入的内容是(套接字描述符,队列的长度)
返回:成功返回0,失败返回-1。

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)

accept() 表示等待接受客户端的连接请求,接收到请求,成功连接后,accept() 返回一个新的套接字,用于与该客户端通信,而原始监听套接字则继续处理新的连接请求。

传入的内容是:(套接字描述符,地址结构体的地址,地址结构体大小的地址)
返回:成功返回新的套接字描述符,失败返回-1 

ssize_t read(int sockfd, void *buf, size_t count)

read() 表示从套接字描述符中读取数据,用于接收客户端发送的消息。读取的数据存储在提供的缓冲区中。

传入的内容是:(套接字描述符,缓冲区指针(数组),要读取的字节数)
返回:成功返回实际读取的字节数,失败返回-1。

ssize_t write(int sockfd, const void *buf, size_t count)

write() 表示向套接字描述符中写入数据,用于向客户端发送响应数据。

传入的内容是:(套接字描述符,缓冲区指针(数组),要写入的字节数)
返回:成功返回实际写入的字节数,失败返回-1。

int close(int sockfd)

close()表示关闭套接字描述符。

传入的内容是:(套接字描述符)
返回:成功返回0,失败返回-1。 


接着解释一下客户端的新出现的函数:

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

connet()表示客户端向服务器发起连接请求。客户端告诉操作系统需要连接到哪个服务器的哪个端口。

传入的内容是:(套接字描述符,地址结构体的地址,地址结构体大小)
返回:成功返回0,失败返回-1。

看完这些,你会发现:套接字描述符和文件描述符很像,都可以根据描述进行写入读取和各种其他操作,其实,这就是UNIX系统和类UNIX系统(Linux系统)的抽象资源管理方式,通过整数来标识系统中的资源,使用统一的接口设计,“一切皆文件”。

看到这里,你一定有几个问题:

1.为什么客户端少了bind()和listen()的操作?

2.为什么connect操作指向了accept操作之后?

3.地址结构体的地址addr是个什么东西?

4.为什么有的函数传addr大小,有的传addr大小的地址?

1.对于服务器端来说,服务器需要绑定到固定的端口这样客户端才能知道它,对于客户端来说,操作系统会在必要的时候分配临时的本地端口和地址,不需要再绑定端口。

2.因为服务器端的accept函数是阻塞的,等待客户端发起请求,当connect发送给服务器端请求之后,才会继续进行后面的读写操作。

3.addr的类型如下:有两个成员,分别是地址族,地址和端口信息,但是这不方便我们进行设置,所以一般采用 sockaddr_in 这个结构,最后在进行强制类型转换得到sockaddr,注意这两个结构体类型大小是一样的,只是结构不一样。

struct sockaddr {sa_family_t sa_family;    // 地址族,例如 AF_INET(IPv4)或 AF_INET6(IPv6)char sa_data[14];         // 地址和端口信息
};

下面是sockaddr_in结构体类型,可以清楚地看到每个成员的含义:

struct sockaddr_in {sa_family_t sin_family;   // 地址族,通常为 AF_INET(IPv4)uint16_t sin_port;        // 端口号(16 位),以网络字节序表示struct in_addr sin_addr;  // IP 地址(32 位)char sin_zero[8];         // 保留字段,填充用
};

4.可以看到accept函数的addrlen参数是 addr 大小(变量)的地址,但是connect和bind函数的addrlen参数是 addr 大小(变量)本身,这是因为accept不知道调用者提供的 addr 缓冲区的大小可能是IPv4可能是IPv6,所以需要地址地址。

我猜测可能和TCP的三次握手或者accept返回新的套接字或者客户端分配动态端口有关系,而connect和bind函数都是用已知的套接字进行操作,所以不会进行addr大小的改变,所以可以直接传值。

这就是TCP编程的两种模式,从下篇文章开始,我们将学习如何编写服务器端和客户端的代码。

这就是文章的所有内容了,希望对你有所帮助,如有错误欢迎指出。

相关文章:

TCP网络编程(一)—— 服务器端模式和客户端模式

这篇文章将会编写基本的服务器网络程序,主要讲解服务器端和客户端代码的原理,至于网络名词很具体的概念,例如什么是TCP协议,不会过多涉及。 首先介绍一下TCP网络编程的两种模式:服务器端和客户端模式: 首先…...

03-类和对象(上)

一、类的概述 1.类的引入 类的封装:将数据和方法封装在一起,加以权限区分,用户只能通过公共方法访问私有数据。 为什么要将数据和方法封装在一起呢,而且还要通过公共方法才能访问私有数据? C语言中数据和方法分开可…...

PCL点云库入门——PCL库点云滤波算法之统计滤波(StatisticalOutlierRemoval)

1、算法原理 统计滤波算法是一种利用统计学原理对点云数据进行处理的方法。它主要通过计算点云中每个点的统计特性,如均值、方差等,来决定是否保留该点。算法首先会设定一个统计阈值,然后对点云中的每个点进行分析。如果一个点的统计特性与周…...

【机器学习】Kaggle实战信用卡反欺诈预测(场景解析、数据预处理、特征工程、模型训练、模型评估与优化)

构建信用卡反欺诈预测模型 建模思路 本项目需解决的问题 本项目通过利用信用卡的历史交易数据,进行机器学习,构建信用卡反欺诈预测模型,提前发现客户信用卡被盗刷的事件。 项目背景 数据集包含由欧洲持卡人于2013年9月使用信用卡进行交的…...

【RISC-V CPU debug 专栏 4 -- RV CSR寄存器介绍】

文章目录 Overview1. CSR寄存器访问指令2. 为何CSR地址不是4字节对齐(1) CSR寄存器空间是独立的地址空间(2) 节省编码空间(3) 对硬件实现的简化 3. CSR的物理大小和对齐无关4. RISC-V 中的 GPR 寄存器及其作用GPR 的详细用途CSR(控制状态寄存器)与 GPR 的…...

Object.defineProperty() 完整指南

Object.defineProperty() 完整指南 1. 基本概念 Object.defineProperty() 方法允许精确地添加或修改对象的属性。默认情况下,使用此方法添加的属性是不可修改的。 1.1 基本语法 Object.defineProperty(obj, prop, descriptor)参数说明: obj: 要定义…...

postgresql函数创建

postgresql的函数创建 1.创建函数的基本语法: CREATE [OR REPLACE] FUNCTION function_name(parameter_list) RETURNS return_type AS $$ BEGIN -- 函数体 END; $$ LANGUAGE language_name;2.创建函数时传入参数示例:add_user tbl_user表 | id | username | …...

ECMAScript 变量

文章目录 前言一、ECMAScript 变量二、var 关键字1、var 声明作用域2、var 声明提升(hoist)三、let 关键字四、const 关键字🔰 总结前言 任何语言的核心所描述的都是这门语言在最基本的层面上如何工作,涉及 语法、操作符、数据类型以及内置功能,在此基础之上才可以构建复…...

CAN总线波形中最后一位电平偏高或ACK电平偏高问题分析

参考:https://zhuanlan.zhihu.com/p/689336144 有时候看到CAN总线H和L的差值波形的最后一位电平会变高很多,这是什么原因呢? 实际上这是正常的现象,最后一位是ACK位。问题描述为:CAN总线ACK电平偏高。 下面分析下原因…...

【C++】22___STL常用算法

目录 一、常用遍历算法 二、常用查找算法 2.1 find 2.2 其它查找算法 三、常用排序算法 3.1 sort 3.2 其它排序算法 四、拷贝 & 替换 4.1 copy 4.2 其它算法 五、常用的算数生成算法 5.1 accumulate 5.2 fill 六、常用集合算法 6.1 set_intersection 6…...

意静明和-十成

十成 责任(健康)、使命(事业)、信念(意义)、自律(排诱)、自修(知识)、总结(四为)、执行(一事不拖)、人情&…...

easyui textbox使用placeholder无效

easyui textbox使用placeholder无效 在easyui 的textbox控件&#xff0c;请使用data-options 设定 示例 <input type text class easyui-textbox data-options "prompt:请输入您的邮箱"/>...

flux中的缓存

1. cache&#xff0c;onBackpressureBuffer。都是缓存。cache可以将hot流的数据缓存起来。onBackpressureBuffer也是缓存&#xff0c;但是当下游消费者的处理速度比上游生产者慢时&#xff0c;上游生产的数据会被暂时存储在缓冲区中&#xff0c;防止丢失。 2. Flux.range 默认…...

代码重定位详解

文章目录 一、段的概念以及重定位的引入1.1 问题的引入1.2 段的概念1.3 重定位 二、如何实现重定位2.1 程序中含有什么&#xff1f;2.2 谁来做重定位&#xff1f;2.3 怎么做重定位和清除BSS段&#xff1f;2.4 加载地址和链接地址的区别 三、散列文件使用与分析3.1 重定位的实质…...

活动预告 | Microsoft 365 在线技术公开课:让组织针对 Microsoft Copilot 做好准备

课程介绍 通过Microsoft Learn免费参加Microsoft 365在线技术公开课&#xff0c;建立您需要的技能&#xff0c;以创造新的机会并加速您对Microsoft云技术的理解。参加我们举办的“让组织针对 Microsoft Copilot for Microsoft 365 做好准备” 在线技术公开课活动&#xff0c;学…...

从0到机器视觉工程师(一):机器视觉工业相机总结

目录 相机的作用 工业相机 工业相机的优点 工业相机的种类 工业相机知名品牌 光源与打光 打光方式 亮暗场照明 亮暗场照明的应用 亮暗场照明的区别 前向光漫射照明 背光照明 背光照明的原理 背光照明的应用 同轴光照明 同轴光照明的应用 总结 相机的作用 相机…...

Docker安装(Docker Engine安装)

一、Docker Engine和Desktop区别 Docker Engine 核心组件&#xff1a;Docker Engine是Docker的核心运行时引擎&#xff0c;负责构建、运行和管理容器。它包括守护进程&#xff08;dockerd&#xff09;、API和命令行工具客户端&#xff08;docker&#xff09;。适用环境&#…...

数组的深度监听deep

场景&#xff1a;组件提供的emit事件可能被占用&#xff0c;在不能使用事件提交的情况下&#xff0c;就要上watch数组监听了&#xff0c;但是是发现只有在数组的长度发生变化的时候才会触发监听&#xff0c;这怎么行。。。。。 对于对象数组的深度监听&#xff0c;如果没有正确…...

点击锁定按钮,锁定按钮要变成解锁按钮,然后状态要从待绑定变成 已锁定(升级版)

文章目录 1、updateInviteCodeStatus2、handleLock3、InviteCodeController4、InviteCodeService5、CrudRepository 点击锁定按钮&#xff0c;锁定按钮要变成解锁按钮&#xff0c;然后状态要从待绑定变成 已锁定&#xff1a;https://blog.csdn.net/m0_65152767/article/details…...

UniApp 性能优化策略

一、引言 在当今数字化时代&#xff0c;移动应用的性能成为影响用户留存与满意度的关键因素。UniApp 作为一款热门的跨平台开发框架&#xff0c;以一套代码适配多端的特性极大提升了开发效率&#xff0c;但同时也面临着性能优化的挑战。优化 UniApp 性能&#xff0c;不仅能够让…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

利用ngx_stream_return_module构建简易 TCP/UDP 响应网关

一、模块概述 ngx_stream_return_module 提供了一个极简的指令&#xff1a; return <value>;在收到客户端连接后&#xff0c;立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量&#xff08;如 $time_iso8601、$remote_addr 等&#xff09;&a…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)

0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述&#xff0c;后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作&#xff0c;其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

cf2117E

原题链接&#xff1a;https://codeforces.com/contest/2117/problem/E 题目背景&#xff1a; 给定两个数组a,b&#xff0c;可以执行多次以下操作&#xff1a;选择 i (1 < i < n - 1)&#xff0c;并设置 或&#xff0c;也可以在执行上述操作前执行一次删除任意 和 。求…...

C# 类和继承(抽象类)

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

Axios请求超时重发机制

Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式&#xff1a; 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

如何理解 IP 数据报中的 TTL?

目录 前言理解 前言 面试灵魂一问&#xff1a;说说对 IP 数据报中 TTL 的理解&#xff1f;我们都知道&#xff0c;IP 数据报由首部和数据两部分组成&#xff0c;首部又分为两部分&#xff1a;固定部分和可变部分&#xff0c;共占 20 字节&#xff0c;而即将讨论的 TTL 就位于首…...

JAVA后端开发——多租户

数据隔离是多租户系统中的核心概念&#xff0c;确保一个租户&#xff08;在这个系统中可能是一个公司或一个独立的客户&#xff09;的数据对其他租户是不可见的。在 RuoYi 框架&#xff08;您当前项目所使用的基础框架&#xff09;中&#xff0c;这通常是通过在数据表中增加一个…...

C++.OpenGL (14/64)多光源(Multiple Lights)

多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...