04_tcp

news2025/1/16 11:08:36

知识点1【多播】

多播地址:

多播地址向以太网MAC地址的映射

UDP多播工作过程:

多播地址结构体:

多播套接口选项:

知识点2【TCP面向链接编程】

1、创建tcp套接字

2、做为客户端需要具备的条件

3、connect链接服务器的函数

4、send函数

5、recv函数

知识点3【TCP服务器】

做为TCP服务器需要具备的条件

1、listen 函数

2、accept函数

知识点4【TCP的三次握手 四次挥手】

1、TCP的三次握手 客户端 connec函数调用的时候发起

2、四次挥手 调用close 激发 底层发送FIN关闭请求

3、close 关闭套接字

知识点1【多播】

多播:

数据的收发仅仅在同一分组中进行

多播的特点:

1、多播地址标示一组接口

2、多播可以用于广域网使用

在IPv4中,多播是可选的

多播地址:

Pv4的D类地址是多播地址

十进制:224.0.0.1 ~ 239.255.255.254 任意一个IP地址 都代表一个多播组

十六进制:E0.00.00.01 à EF.FF.FF.FE

多播地址向以太网MAC地址的映射

UDP多播工作过程:

总结:1、主机先加入多播组 2、往多播组发送数据

多播地址结构体:

在IPv4因特网域(AF_INET)中,多播地址结构体用如下结构体ip_mreq表示

多播套接口选项:

int setsockopt(int sockfd, int level,int optname,   
                const void *optval, socklen_t optlen);
成功执行返回0,否则返回-1

level

optname

说明

optval类型

IPPROTO_IP

IP_ADD_MEMBERSHIP

加入多播组

ip_mreq{}

IP_DROP_MEMBERSHIP

离开多播组

ip_mreq{}

只能将自己加入到某个多播组

#include<stdio.h>
#include<string.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <fcntl.h>
//将主机 加入到多播组 224.0.0.2  接受
int main()
{
	int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	
	//让sockfd有一个固定的IP端口
	struct sockaddr_in my_addr;
	bzero(&my_addr,sizeof(my_addr));
	my_addr.sin_family = AF_INET;
	my_addr.sin_port = htons(8000);
	my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	bind(sockfd, (struct sockaddr *)&my_addr,sizeof(my_addr));
	
	//将192.168.0.111 加入到多播组 224.0.0.2中
	struct ip_mreq mreq;
	mreq.imr_multiaddr.s_addr = inet_addr("224.0.0.2");
	mreq.imr_interface.s_addr = htonl(INADDR_ANY);
	setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,sizeof(mreq));
	
	while(1)
	{
		unsigned char buf[1500]="";
		recvfrom(sockfd,buf,sizeof(buf), 0,NULL,NULL);
		printf("buf=%s\n", buf);
	}
	
	close(sockfd);
	return 0;
}

 运行结果:

知识点2【TCP面向链接编程】

TCP回顾

1、面向连接的流式协议;可靠、出错重传、且每收到一个数据都要给出相应的确认

2、通信之前需要建立链接

3、服务器被动链接,客户端是主动链接

TCP与UDP的差异:

TCP C/S架构

1、创建tcp套接字

2、做为客户端需要具备的条件

1、知道“服务器”的ip、port

2、Connect主动连接“服务器”

3、需要用到的函数

socket—创建“主动TCP套接字”

connect—连接“服务器”

send—发送数据到“服务器”

recv—接受“服务器”的响应

close—关闭连接

3、connect链接服务器的函数

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

功能:

主动跟服务器建立链接

参数:

sockfd:socket套接字

addr:   连接的服务器地址结构

len:  地址结构体长度

返回值:

成功:0    失败:其他

注意:

1、connect建立连接之后不会产生新的套接字

2、连接成功后才可以开始传输TCP数据

3、头文件:#include

4、send函数

ssize_t send(int sockfd, const void* buf,size_t nbytes, int flags);

功能:

用于发送数据

参数:

sockfd: 已建立连接的套接字

buf:    发送数据的地址

nbytes:  发送缓数据的大小(以字节为单位)

flags:    套接字标志(常为0)

返回值:

成功发送的字节数

头文件:

#include<sys/socket.h>

5、recv函数

ssize_t recv(int sockfd, void *buf, size_t nbytes, int flags);

功能:

用于接收网络数据

参数:

sockfd:套接字

buf: 接收网络数据的缓冲区的地址

nbytes: 接收缓冲区的大小(以字节为单位)

flags: 套接字标志(常为0)

返回值:

成功接收到字节数

头文件:

#include<sys/socket.h>

案例:TCP客户端

#include<stdio.h>
#include<string.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <fcntl.h>
//TCP客户端
int main()
{
	//创建一个TCP套接字 SOCK_STREAM
	int sockfd = socket(AF_INET, SOCK_STREAM, 0);
	printf("sockfd = %d\n", sockfd);
	
	//bind是可选的
	struct sockaddr_in my_addr;
	bzero(&my_addr,sizeof(my_addr));
	my_addr.sin_family = AF_INET;
	my_addr.sin_port = htons(9000);
	my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	bind(sockfd,(struct sockaddr *)&my_addr,sizeof(my_addr));
	
	//connect链接服务器
	struct sockaddr_in ser_addr;
	bzero(&ser_addr,sizeof(ser_addr));
	ser_addr.sin_family = AF_INET;
	ser_addr.sin_port = htons(8000);//服务器的端口
	ser_addr.sin_addr.s_addr = inet_addr("192.168.0.110");//服务器的IP
	//如果sockfd没有绑定固定的IP以及端口 在调用connect时候 系统给sockfd分配自身IP以及随机端口
	connect(sockfd, (struct sockaddr *)&ser_addr,sizeof(ser_addr));
	
	//给服务器发送数据 send
	printf("发送的消息:");
	char buf[128]="";
	fgets(buf,sizeof(buf),stdin);
	buf[strlen(buf)-1]=0;
	send(sockfd, buf, strlen(buf), 0);
	
	//接收服务器数据 recv
	char msg[128]="";
	recv(sockfd, msg,sizeof(msg), 0);
	printf("服务器的应答:%s\n", msg);
	
	//关闭套接字
	close(sockfd);
	return 0;
}

运行结果: 

知识点3【TCP服务器】

做为TCP服务器需要具备的条件

1、具备一个可以确知的地址 bind

2、让操作系统知道是一个服务器,而不是客户端 listen

3、等待连接的到来 accpet

对于面向连接的TCP协议来说,连接的建立才真正意味着数据通信的开始.

1、listen 函数

int listen(int sockfd, int backlog);

功能:

将套接字由主动修改为被动。

使操作系统为该套接字设置一个连接队列,用来记录所有连接到该套接字的连接。

参数:

sockfd: socket监听套接字

backlog:连接队列的长度

返回值:

成功:返回0

2、accept函数

int accept(int sockfd,struct sockaddr *cliaddr, socklen_t *addrlen);

功能:

从已连接队列中取出一个已经建立的连接,如果没有任何连接可用,则进入睡眠等待(阻塞)

参数:

sockfd: socket监听套接字

cliaddr: 用于存放客户端套接字地址结构

addrlen:套接字地址结构体长度的地址

返回值:

已连接套接字

头文件:

#include<sys/socket.h>

注意:

返回的是一个已连接套接字,这个套接字代表当前这个连接

#include<stdio.h>
#include<string.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <fcntl.h>

int main()
{
	//1、创建一个tcp监听套接字
	int sockfd = socket(AF_INET, SOCK_STREAM, 0);
	
	//2、使用bind函数 给监听套接字 绑定固定的ip以及端口
	struct sockaddr_in my_addr;
	bzero(&my_addr,sizeof(my_addr));
	my_addr.sin_family = AF_INET;
	my_addr.sin_port = htons(8000);
	my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	bind(sockfd, (struct sockaddr *)&my_addr, sizeof(my_addr));
	
	//3、使用listen创建连接队列 主动变被动
	listen(sockfd, 10);
	
	//4、使用accpet函数从连接队列中 提取已完成的连接 得到已连接套接字
	struct sockaddr_in cli_addr;
	socklen_t cli_len = sizeof(cli_addr);
	int new_fd = accept(sockfd, (struct sockaddr *)&cli_addr, &cli_len);
	//new_fd代表的是客户端的连接   cli_addr存储是客户端的信息
	char ip[16]="";
	inet_ntop(AF_INET,&cli_addr.sin_addr.s_addr, ip,16);
	printf("客户端:%s:%hu连接了服务器\n",ip,ntohs(cli_addr.sin_port));
	
	//5、获取客户端的请求 以及 回应客户端
	char buf[128]="";
	recv(new_fd, buf,sizeof(buf),0);
	printf("客户端的请求为:%s\n",buf);
	
	send(new_fd,"recv", strlen("recv"), 0);
	
	
	//6、关闭已连接套接字
	close(new_fd);
	
	//7、关闭监听套接字
	close(sockfd);
	
	return 0;
}

 运行结果:

知识点4【TCP的三次握手 四次挥手】

1、TCP的三次握手 客户端 connec函数调用的时候发起

SYN是一个链接请求:是TCP报文中的某一个二进制位

第一次握手:客户端 发送SYN请求 链接服务器

第二次握手:服务器 ACK回应客户端的链接请求 同时 服务器给客户端发出链接请求

第三次握手:客户端 ACK回应 服务器的链接请求

2、四次挥手 调用close 激发 底层发送FIN关闭请求

不缺分客户端 或 服务器先后问题。

第一次挥手:A调用close 激发底层 发送FIN关闭请求 并且A处于半关闭状态

第二次挥手:B的底层给A回应ACK 同时导致B的应用层recv/read收到0长度数据包

第三次挥手:B调用close 激发底层给A发送FIN关闭请求 并且B处于半关闭状态

第四次挥手:A的底层给B回应ACK 同时 A处于完全关闭状态,B收到A的ACK也处于完全关闭状态

3、close 关闭套接字

 

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

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

相关文章

地图下载白嫖神器!你该怎么用好它

今天介绍一下做数据可视化网站比较好的两个平台。一个是阿里云的Datav&#xff0c;另一个是易智微easyv. 一、DataV.GeoAtlas 前段时间 我们就给大家分享过阿里云的DataV.GeoAtlas地理小工具系列。我们可以通过这个平台下载高德比较新的地图数据&#xff0c;数据的时效性是有较…

如何查看SAP版本及HANA版本?

目录 一、查SAP NetWeaver版本 二、查看S/4 HANA版本 在SAP运维及系统集成时&#xff0c;经常外面公司问及本公司的SAP版本及HANA版本。其实是每一个登录SAP的用户都可以查到的。方法如下&#xff1a; 一、查SAP NetWeaver版本 SAP界面上选择菜单&#xff1a;系统-状态&am…

哈夫曼树与哈夫曼编码

哈夫曼树&#xff1a;结点中赋予一个某种意义的值&#xff0c;称为结点的权值&#xff0c;从根结点开始&#xff0c;到目标结点经过的边数&#xff0c;称为路径长度&#xff0c;路径长度乘以权值&#xff0c;称为带权路径长度&#xff1b; 例如&#xff1a;根结点代表着快递集…

上位机工业协议-S7COMM

1、S7协议主要针对西门子相关设备通信。先了解基本通信对象、通信环境、通信报文&#xff0c;再处理S7COMM通信库的封装与测试。 2、西门子设备通信 - PLC&#xff1a;系列 LOGO、200、200Smart、300、400、1200、1500 - PLC&#xff1a;LOGO、200、200Smart、300、400、1…

Elastic Stack容器化部署拓展(Https、AD域集成)并收集Cisco设备的日志信息

前言&#xff1a; 还记得在去年的笔记中提到过EFK&#xff08;Elasticsearch-Filebeat-Kibana&#xff09;的部署&#xff0c;但是其中的内容相对简单&#xff0c;也没有提到一些额外的Elastic Stack的特性。链接如下&#xff1a;https://blog.csdn.net/tushanpeipei/article/…

JSTL使用

目录 简介&#xff1a; 组成 使用&#xff1a; code核心库使用 ​编辑 fmt格式化 ​编辑 简介&#xff1a; 全称:JSP Standard Tag Library 中文名:JSP标准标签库 作用:用于扩展JSP中的标签&#xff0c;能够为JSP页面提供流程控制、类型转换等功能的标签。替换JSP中代码…

【Spring Cloud实战】Ribbon负载均衡

gitee地址&#xff1a;https://gitee.com/javaxiaobear/spring-cloud_study.git 在线阅读地址&#xff1a;https://javaxiaobear.gitee.io/ 1、概述 Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。 简单的说&#xff0c;Ribbon是Netflix发布的开源项…

jenkins持续集成 自动化部署

一、环境准备 1.1 Java环境 &#xff08;1&#xff09;安装jdk1.8 yum -y install java-1.8.0-openjdk* &#xff08;2&#xff09;执行以下命令查看是否安装成功 java -version 1.2 安装maven &#xff08;1&#xff09;将安装包上传到Linux服务器&#xff0c;解压缩 tar -…

对笔记本电池的研究

文章目录设计容量&完全充电容量笔记本电池报告显示电池设计与系统电池的全部充电容量之间的差异解释电池损耗正确做法查看笔记本的电池使用报告方法第一步&#xff1a;WinR键输入cmd&#xff0c;打开命令提示符窗口第二步&#xff1a;输入powercfg /batteryreport&#xff…

代码规范-对抗软件复杂度

1、为什么需要代码规范 任何系统性的项目都需要架构设计&#xff0c;而架构设计的核心命题是控制复杂度。 但随着项目的不断迭代&#xff0c;复杂度就会不断上升&#xff0c;研发效率就会不断下降。 而代码规范正是对抗软件复杂度的有效手段&#xff0c;通过约定俗成的规则…

[附源码]计算机毕业设计JAVA户籍管理系统

[附源码]计算机毕业设计JAVA户籍管理系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis M…

docker安装redis详细教程

1、下载最新redis镜像 docker pull redis //表示拉取最新的镜像 如果要指定版本 docker pull redis:latest//表示拉取最新的镜像 2、创建redis映射目录 mkdir /redisData/redis/conf 配置文件挂载在我指定的redisData/redis/conf/ 文件夹中&#xff0c;方便后续的修改 创建re…

Linux上单机部署RocketMq

Linux上单机部署RocketMq1、安装jdk2、下载rocketmq并解压3、创建日志文件夹4、启动namesrv5、启动broker6、查看和关闭7、rocketmq控制台7.1、控制台idea启动7.2、控制台jar包启动1、安装jdk rocketmq的运行是建立在jdk之上的&#xff0c;所以&#xff0c;我们要搭建rocketmq服…

uView u-slider 自定义滑块

有个需求UI设计的滑动选择器中的滑块如下所示&#xff1a; 项目中集成的是vView2.0组件库&#xff0c;u-slider组件中有 blockStyle 属性&#xff0c;看着是用来设置自定义滑块的。但是试了下&#xff0c;没有效果&#xff0c;不知怎么回事。看了一下uView1.0组件库 u-slider组…

大学生想做兼职应该怎么找,适合大学生的线上线下靠谱兼职推荐

大学生现在有很多兼职工作可以在网上和实体上做。他们可以根据个人能力和喜好进行选择。以下是一些低门槛的在线和离线兼职工作&#xff0c;希望能帮助到你。 线下兼职 1.勤工助学岗位 学校&#xff1a;通过学校提供的勤工俭学岗位&#xff0c;如办公室助理、图书馆助理等&am…

Java 线上机器 CPU 100% 的一次排查过程

文章目录1. 问题发生2. 数据库连接关闭问题排查3. 问题的进一步排查4. 解决方法1. 问题发生 日常敲代码突然收到生产环境异常告警&#xff0c;线上有一台机器 CPU 使用率飙升到 100 触发扩容&#xff0c;工作群里一下子鸡飞狗跳。 出现问题&#xff0c;首先当然是查看监控和日…

如何画架构图?

平时做过一些系统设计&#xff0c;也写过一些系统分析文章&#xff0c;从组件、关系、交互等方面提供一些建议&#xff0c;并用我之前写文章画的一些图举些例子。构成系统的组件通过形状、颜色、名称来逼近其概念。LevelDB 主要构件如上面 LevelDB 的架构图&#xff0c;包含的主…

Redis哨兵(Sentinel)

# Redis哨兵(Sentinel) Redis 的 Sentinel 系统用于管理多个 Redis 服务器&#xff08;instance&#xff09;&#xff0c; 该系统执行以下三个任务&#xff1a; 监控&#xff08;Monitoring&#xff09;&#xff1a; Sentinel 会不断地检查你的主服务器和从服务器是否运作正常…

内核参数 sched_min_granularity_ns 为什么看不到啦?

linux内核从版本v5.13-rc1起&#xff08;含&#xff09;&#xff0c;sysctl 已无法设置 kernel.sched_min_granularity_ns。 其实不止sched_min_granularity_ns&#xff0c;在 /proc/sys/kernel 下&#xff0c;和CPU调度相关的6个参数都不见了&#xff1a; sched_latency_ns …

Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1(七)射线抓取

文章目录&#x1f4d5;教程说明&#x1f4d5;添加射线功能的相关组件&#x1f4d5;设置 Interaction Layer Mask&#x1f4d5;让 XR Direct Interactor 不对 XR Ray Interactor 产生干扰&#x1f4d5;使抓取的物体不会吸到手上&#x1f4d5;远距离抓取时通过摇杆改变抓取物体的…