一、TCP

TCP : 传输控制协议   传输层

1. TCP特点

(1).面向连接,避免部分数据丢失
(2).安全、可靠
(3).面向字节流
(4).占用资源开销大

2.TCP安全可靠机制

三次握手:指建立tcp连接时,需要客户端和服务端总共发送三次报文确认连接。确保双方均已做好                  收发数据的准备-----只能由客户端发起

ACK:响应报文    SYN(TPC头部标志位)请求建立连接     FIN请求断开连接

四次挥手:断开一个tcp连接,需要客户端和服务端发送四个报文以确认断开。确保断开连接前收                    发数据均已完成 ,当服务端没有数据需要发送,即不需要建立下一次连接时,服务端将                          ACK和FIN一起发送出去,即三次挥手. 三次挥手不能确认服务端每一次有无下一次连接.

3.TCP

:服务端创建了两个套接字,recv里接接收的是第二个套接字(通信套接字)

(1).socket

 socket(AF_INET, SOCK_STREAM, 0);

(2).connect

  int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
功能:发送三次握手链接请求
参数:sockfd:套接字文件描述符
addr:存放目的地址空间首地址
addrlen:目的地址长度
返回值: 成功返回0  失败返回-1

(3).send

 ssize_t send(int sockfd, const void *buf, size_t len, int flags);
功能:发送数据
参数:sockfd:套接字文件描述符
buf:存放数据空间首地址
len:数据长度
flag:属性默认为0 
返回值:成功返回发送字节数  ;  失败返回-1 

(4).recv

 ssize_t recv(int sockfd, void *buf, size_t len, int flags);
功能:接收数据 
参数:sockfd:套接字文件描述符
buf:存放数据空间首地址 
len:最多接收数据长度 
flags:接收属性默认为0 
返回值:成功返回实际接收字节数  ;  失败返回-1 ;  连接断开返回0 

(5).bind

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

(6).listen

int listen(int sockfd, int backlog);
功能:监听三次握手链接请求
参数:sockfd:套接字文件描述符
backlog:最多允许等待尚未处理的三次握手链接个数
返回值:成功返回0 ; 失败返回-1 

(7).accept

  int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
功能:处理三次握手等待队列中的第一个请求并建立一个用来通信的新套接字
参数:sockfd:套接字文件描述符
addr:存放发送端IP地址空间首地址 
addrlen:想要接收的IP地址的长度 
返回值:成功返回新文件描述符(通讯套接字) ; 失败返回-1 

4. TCP报文头

标志位:

(1). URG: 紧急指针标志, 为1时表示紧急指针有效, 该报文应该优先传送。
(2). ACK: 确认应答标志
(3). PSH:  表示发送数据,提示接收端从TCP接收缓冲区中读走数据,为接收后续数据腾出空间
(4). RST: 重置连接标志
(5). SYN: 表示请求建立一个连接
(6). FIN: finish标志, 表示释放连接

滑动窗口大小:是TCP流量控制得一个手段。目的是告诉对方, 本端得TCP接受缓冲区还能容纳                              多少字节得数据,
这样对方就可以控制发送数据的速度,从而达到流量控制,16bit,2字节,因而窗口最大65535.

5. TCP的机制

TCP复杂是因为它既要保证可靠性,同时又要尽可能的提高性能。

可靠性:

(1) 三次握手和四次挥手机制
(2) 确认应答:TCP将每个字节的数据都进行了编号,即为序列号。每一个ACK都带有对应的确认 序列号,保证数据不丢失的按序到达
(3) 超时重传:当发送端发送的数据在网络中丢失时,在一定时间内没有收到接收端的ACK,则发送端会重新发送丢失数据。
(4)流量控制:按照ACK中“窗口大小”字段控制发送端的发送速度

提高性能:

(1)滑动窗口(缓冲区):可以按照“窗口大小”, 一次发送多条后, 再等待应答。


(2)延迟应答:当接收方处理速度很快时,可以延迟发送ACK,此时"窗口大小"会自动增大
(3)捎带应答:搭载应用层的响应报文发送ACK。

 6. TCP粘包问题----面试题

TCP协议是面向字节流的协议,接收方不知道消息的界限,不知道一次提取多少数据,这就造成了粘包问题。

粘包问题出现的原因: (接受发送速率不匹配)

(1). 发送端:发送方发送数据过快,造成粘包;
(2). 接收端:不及时的接收缓冲区内的包,造成多个包接收。接收过慢.

避免粘包问题的方法:(usleep())

(1). 对于定长的包,发送固定大小字节的数据,保证每次都按固定大小读取即可;//  结构体

     问题:1)结构体对齐问题(比如:指定按1字节对齐),不能放指针

             2)发送数据类型多样化时,接收方难区分接受大小

(2). 对于变长的包,还可以在包和包之间使用明确的数据分隔符,这个分隔符是由程序员自己来定的,只要保证分隔符不和正文冲突即可。

eg:hello world\n how are you\n xxxx\n

应用层可以根据\n进行解析

(3).自定义应用层的协议帧

帧头: AA 1字节

有效数据长度: len 1字节

帧尾: BB 1字节

校验:8bits和校验(1字节)  16bits和校验(2字节)    CRC校验

二、练习 

1.使用tcp实现双人聊天

//cli.c
#include "head.h"int init_tcp_cli(const char *ip, unsigned short port)
{int sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0){perror("fail socket");return -1;}struct sockaddr_in seraddr;seraddr.sin_family = AF_INET;seraddr.sin_port = htons(port);seraddr.sin_addr.s_addr = inet_addr(ip);int ret = connect(sockfd, (struct sockaddr *)&seraddr, sizeof(seraddr));if (ret < 0){perror("fail connect");return -1;}return sockfd;
}void *send_msg(void *arg)
{char buff[1024] = {0};int sockfd = *((int *)arg);while (1){memset(buff, 0, sizeof(buff));fgets(buff ,sizeof(buff), stdin);send(sockfd, buff, strlen(buff), 0);}return NULL;
}void *recv_msg(void *arg)
{char buff[1024] = {0};int sockfd = *((int *)arg);while (1){memset(buff, 0, sizeof(buff));ssize_t size = recv(sockfd, buff, sizeof(buff), 0);if (size < 0){perror("fail recv");break;}else if (0 == size){printf("connect lost\n");break;}printf("B-->A: %s\n", buff);}return NULL;
}int main(int argc, const char *argv[])
{pthread_t tid[2];int sockfd = init_tcp_cli("192.168.1.162", 50000);if (sockfd < 0){return -1;}pthread_create(&tid[0], NULL, send_msg, &sockfd);pthread_create(&tid[1], NULL, recv_msg, &sockfd);pthread_join(tid[0], NULL);pthread_join(tid[1], NULL);close(sockfd);return 0;
}
//ser.c
#include "head.h"int init_tcp_ser(const char *ip, unsigned short port)
{int sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0){perror("fail socket");return -1;}struct sockaddr_in seraddr;seraddr.sin_family = AF_INET;seraddr.sin_port = htons(port);seraddr.sin_addr.s_addr = inet_addr(ip);int ret = bind(sockfd, (struct sockaddr *)&seraddr, sizeof(seraddr));if (ret < 0){perror("fail bind");return -1;}ret = listen(sockfd, 10);if (ret < 0){perror("fail listen");return -1;}return sockfd;
}void *send_msg(void *arg)
{char buff[1024] = {0};int sockfd = *((int *)arg);while (1){memset(buff, 0, sizeof(buff));fgets(buff ,sizeof(buff), stdin);send(sockfd, buff, strlen(buff), 0);}return NULL;
}void *recv_msg(void *arg)
{char buff[1024] = {0};int connfd = *((int *)arg);while (1){memset(buff, 0, sizeof(buff));ssize_t size = recv(connfd, buff, sizeof(buff), 0);if (size < 0){perror("fail recv");break;}else if (0 == size){printf("connect lost\n");break;}printf("A-->B: %s\n", buff);}return NULL;
}int main(int argc, const char *argv[])
{pthread_t tid[2];int sockfd = init_tcp_ser("192.168.1.162", 50000);if (sockfd < 0){return -1;}int connfd = accept(sockfd, NULL, NULL);if (connfd < 0){perror("fail accpet");return -1;}pthread_create(&tid[0], NULL, send_msg, &connfd);pthread_create(&tid[1], NULL, recv_msg, &connfd);pthread_join(tid[0], NULL);pthread_join(tid[1], NULL);close(connfd);close(sockfd);return 0;
}
#ifndef __HEAD_H__
#define __HEAD_H__#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>#endif

 2.使用tcp实现文件发送()

//cli.c
#include "head.h"int init_tcp_cli(const char *ip, unsigned short port)
{int sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0){perror("fail socket");return -1;}struct sockaddr_in seraddr;seraddr.sin_family = AF_INET;seraddr.sin_port = htons(port);seraddr.sin_addr.s_addr = inet_addr(ip);int ret = connect(sockfd, (struct sockaddr *)&seraddr, sizeof(seraddr));if (ret < 0){perror("fail connect");return -1;}return sockfd;
}int send_file(int sockfd, const char *filename)
{send(sockfd, filename, strlen(filename), 0);usleep(10);int fd = open(filename, O_RDONLY);if (fd < 0){perror("fail open");return -1;}char buff[1024] = {0};while (1){ssize_t size = read(fd, buff, sizeof(buff));if (size <= 0){break;}send(sockfd, buff, size, 0);}close(fd);return 0;
}int main(int argc, const char *argv[])
{int sockfd = init_tcp_cli("192.168.1.162", 50000);if (sockfd < 0){return -1;}send_file(sockfd, "1.jpg");close(sockfd);return 0;
}
//ser.c
#include "head.h"int init_tcp_ser(const char *ip, unsigned short port)
{int sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0){perror("fail socket");return -1;}struct sockaddr_in seraddr;seraddr.sin_family = AF_INET;seraddr.sin_port = htons(port);seraddr.sin_addr.s_addr = inet_addr(ip);int ret = bind(sockfd, (struct sockaddr *)&seraddr, sizeof(seraddr));if (ret < 0){perror("fail bind");return -1;}ret = listen(sockfd, 10);if (ret < 0){perror("fail listen");return -1;}return sockfd;
}int recv_file(int connfd)
{char buff[1024] = {0};char fileneme[1024] = {0};recv(connfd, fileneme, sizeof(fileneme), 0);printf("fileneme = %s\n", fileneme);int fd = open(fileneme, O_WRONLY | O_CREAT | O_TRUNC, 0664);if (fd < 0){perror("fail open");return -1;}while (1){ssize_t size = recv(connfd, buff, sizeof(buff), 0);if (size <= 0){break;}write(fd, buff, size);}close(fd);return 0;
}int main(int argc, const char *argv[])
{int sockfd = init_tcp_ser("192.168.1.162", 50000);if (sockfd < 0){return -1;}int connfd = accept(sockfd, NULL, NULL);if (connfd < 0){perror("fail accpet");return -1;}recv_file(connfd);close(connfd);close(sockfd);return 0;
}

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

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

相关文章

【爬虫】06 - 自动化爬虫selenium

自动化爬虫selenium 文章目录自动化爬虫selenium一&#xff1a;Selenium简介1&#xff1a;什么是selenium2&#xff1a;安装准备二&#xff1a;元素定位1&#xff1a;id 定位2&#xff1a;name 定位3&#xff1a;class 定位4&#xff1a;tag 定位5&#xff1a;xpath 定位(最常用…

2025年中国移动鸿鹄大数据实训营(大数据方向)kafka讲解及实践-第2次作业指导

书接上回&#xff0c;第二次作业比较容易解决&#xff0c;我问了ai&#xff0c;让他对我进行指导&#xff0c;按照它提供的步骤&#xff0c;我完成了本次实验&#xff0c;接下来我会标注出需要注意的细节&#xff0c;指导大家完成此次任务。 &#x1f3af; 一、作业目标 ✔️…

三十七、【高级特性篇】定时任务:基于 APScheduler 实现测试计划的灵活调度

三十七、【高级特性篇】定时任务:基于 APScheduler 实现测试计划的灵活调度 前言 准备工作 第一部分:后端实现 - `APScheduler` 集成与任务调度 1. 安装 `django-apscheduler` 2. 配置 `django-apscheduler` 3. 数据库迁移 4. 创建调度触发函数 5. 启动 APScheduler 调度器 6…

RabbitMQ--消息顺序性

看本章之前强烈建议先去看博主的这篇博客 RabbitMQ--消费端单线程与多线程-CSDN博客 一、消息顺序性概念 消息顺序性是指消息在生产者发送的顺序和消费者接收处理的顺序保持一致。 二、RabbitMQ 顺序性保证机制 情况顺序保证情况备注单队列&#xff0c;单消费者消息严格按发送顺…

.net core接收对方传递的body体里的json并反序列化

1、首先我在通用程序里有一个可以接收对象型和数组型json串的反序列化方法public static async Task<Dictionary<string, string>> AllParameters(this HttpRequest request){Dictionary<string, string> parameters QueryParameters(request);request.Enab…

(10)机器学习小白入门 YOLOv:YOLOv8-cls 模型评估实操

YOLOv8-cls 模型评估实操 (1)机器学习小白入门YOLOv &#xff1a;从概念到实践 (2)机器学习小白入门 YOLOv&#xff1a;从模块优化到工程部署 (3)机器学习小白入门 YOLOv&#xff1a; 解锁图片分类新技能 (4)机器学习小白入门YOLOv &#xff1a;图片标注实操手册 (5)机器学习小…

Vue 脚手架基础特性

一、ref属性1.被用来给元素或子组件注册引用信息&#xff08;id的替代者&#xff09;2.应用在html标签上获取的是真实DOM元素&#xff0c;用在组件标签上是组件实例对象3.使用方式&#xff1a;(1).打标识&#xff1a;<h1 ref"xxx">...</h1> 或 <Schoo…

Ubuntu安装k8s集群入门实践-v1.31

准备3台虚拟机 在自己电脑上使用virtualbox 开了3台1核2G的Ubuntu虚拟机&#xff0c;你可以先安装好一台&#xff0c;安装第一台的时候配置临时调高到2核4G&#xff0c;安装速度会快很多&#xff0c;安装完通过如下命令关闭桌面&#xff0c;能够省内存占用&#xff0c;后面我们…

Word Press富文本控件的保存

新建富文本编辑器&#xff0c;并编写save方法如下&#xff1a; edit方法&#xff1a; export default function Edit({ attributes, setAttributes }) {return (<><div { ...useBlockProps() }><RichTexttagNameponChange{ (value) > setAttributes({ noteCo…

【编程趣味游戏】:基于分支循环语句的猜数字、关机程序

&#x1f31f;菜鸟主页&#xff1a;晨非辰的主页 &#x1f440;学习专栏&#xff1a;《C语言学习》 &#x1f4aa;学习阶段&#xff1a;C语言方向初学者 ⏳名言欣赏&#xff1a;"编程的核心是实践&#xff0c;而非空谈" 目录 1. 游戏1--猜数字 1.1 rand函数 1.2 sr…

UE5 UI 控件切换器

文章目录分类作用属性分类 面板 作用 可以根据索引切换要显示哪个子UI&#xff0c;可以拥有多个子物体&#xff0c;但是任何时间只能显示一个 属性 在这里指定要显示的UI的索引

scikit-learn 包

文章目录scikit-learn 包核心功能模块案例其他用法**常用功能详解****(1) 分类任务示例&#xff08;SVM&#xff09;****(2) 回归任务示例&#xff08;线性回归&#xff09;****(3) 聚类任务示例&#xff08;K-Means&#xff09;****(4) 特征工程&#xff08;PCA降维&#xff0…

Excel 将数据导入到SQLServer数据库

一般系统上线前期都会导入期初数据&#xff0c;业务人员一般要求你提供一个Excel模板&#xff0c;业务人员根据要求整理数据。SQLServer管理工具是支持批量导入数据的&#xff0c;所以我们可以使用该工具导入期初。Excel格式 第一行为字段1、连接登入的数据库并且选中你需要导入…

剪枝和N皇后在后端项目中的应用

剪枝算法&#xff08;Pruning Algorithm&#xff09; 生活比喻&#xff1a;就像修剪树枝一样&#xff0c;把那些明显不会结果的枝条提前剪掉&#xff0c;节省养分。 在后端项目中的应用场景&#xff1a; 搜索优化&#xff1a;在商品搜索中&#xff0c;如果某个分类下没有符合条…

cocos 2d游戏中多边形碰撞器会触发多次,怎么解决

子弹打到敌机 一发子弹击中&#xff0c;碰撞回调多次执行 我碰撞组件原本是多边形碰撞组件 PolygonCollider2D&#xff0c;我改成盒碰撞组件BoxCollider2D 就好了 用前端的节流方式。或者loading处理逻辑。我测试过了&#xff0c;是可以 本来就是多次啊,设计上貌似就是这样的…

Kubernetes环境中GPU分配异常问题深度分析与解决方案

Kubernetes环境中GPU分配异常问题深度分析与解决方案 一、问题背景与核心矛盾 在基于Kubernetes的DeepStream应用部署中&#xff0c;GPU资源的独占性分配是保障应用性能的关键。本文将围绕一个典型的GPU分配异常问题展开分析&#xff1a;多个请求GPU的容器本应独占各自的GPU&…

Django与模板

我叫补三补四&#xff0c;很高兴见到大家&#xff0c;欢迎一起学习交流和进步今天来讲一讲视图Django与模板文件工作流程模板引擎&#xff1a;主要参与模板渲染的系统。内容源&#xff1a;输入的数据流。比较常见的有数据库、XML文件和用户请求这样的网络数据。模板&#xff1a…

日本上市IT企业|8月25日将在大连举办赴日it招聘会

株式会社GSD的核心战略伙伴贝斯株式会社&#xff0c;将于2025年8月25日在大连香格里拉大酒店商务会议室隆重举办赴日技术人才专场招聘会。本次招聘会面向全国范围内的优秀IT人才&#xff0c;旨在为贝斯株式会社东京本社长期发展招募优质的系统开发与管理人才。招聘计划&#xf…

低功耗设计双目协同画面实现光学变焦内带AI模型

低功耗设计延长续航&#xff0c;集成储能模块保障阴雨天气下的铁塔路线的安全一、智能感知与识别技术 多光谱融合监控结合可见光、红外热成像、激光补光等技术&#xff0c;实现全天候监测。例如&#xff0c;红外热成像可穿透雨雾监测山火隐患&#xff0c;激光补光技术则解决夜间…

datasophon下dolphinscheduler执行脚本出错

执行hive脚本出错&#xff1a; 错误消息&#xff1a; FAILED: RuntimeException Error loading hooks(hive.exec.post.hooks): java.lang.ClassNotFoundException: org.apache.atlas.hive.hook.HiveHookat java.net.URLClassLoader.findClass(URLClassLoader.java:387)at java.…