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

linux TCP

通信

  • 管道:有名管道、无名管道

  • 信号:异步操作

    • kill 发送信号
    • signal 注册信号
  • 共享内存:通信效率高

  • 消息队列:增强管道,添加数据标识符

  • 信号量:用于通信过程中的数据同步

    • system-vPOSIX(有名,无名)
  • 网络:套接字文件

通信理论

  • 通信特征:

    • 局域网通信时要求通信设备IP地址在同一个网段(IPV4的前三)

    • 在不同设备之间通信时,通信协议必须一致

  • soceket :套接字文件,特殊文件,可收发,使用函数打开

  • IP : 32位点分式IP地址

  • 端口号:2个字节的短整型(1-65535),自用端口号一般设置大于10000

  • 字节序:在X86一般是小端模式;在网络中一般是大端模式

通信协议

IP : 网际协议,给数据分配目标地址,通过路由器将数据转发

  • TCP : 传输控制协议,在IP的基础上提供可靠的数据传输,确保两端通信成功
  • UDP : 用户数据报协议,在IP的基础上提供快速、简单的数据传输,不考虑接收情况
TCPUDPIP
协议层传输层传输层网络层
连接性(主要)面向连接可无连接无连接
可靠性(主要)可靠,需两端连接成功不可靠,无需两端连接成功不可靠,用于寻址
传输速率
场景文件传输(HTTP直播、实时视频所有网络数据传输

通信模型

  • 七层模型(OSI):理论上的模型 各层协议

    • 应用层: 生成数据 DNS Telnet HTTP FTP
    • 表示层: 加密数据,形成数据包 NA
    • 会话层: 管理对话 NA
    • 传输层: 实现管理下面的通讯子网提供定位端到端 TCP UDP
    • 网络层: 寻找对应地址 IP
    • 数据链路层:传输数据 PPP CSLIP
    • 物理层: 通过网络传输数据包 ISO2110 IEEE802 IEEE802.2
  • 四层模型(TCP/IP):实际应用

    • 应用层: 整合应用层、表示层、会话层
    • 传输层:会话管理,
    • 网络层:找到对应的地址,
    • 网络接口层: 整合数据链路层、物理层,将二进制转化成数据帧
三次握手
  • 第一次握手:客户端发送一个 SYN给服务器,客户端进入SYN_SEND 状态,然后等待服务器的回发确认信息;
    第二次握手: 服务器发一个 SYN+ACK 给客户端,确认已经收到客户端发来的信息,此时服务器进入SYN_RECV状态;
    第三次握手:客户端接收到服务器发来的确认信息后,再反馈一个 ACK给服务器,完成三次握手,客户端和服务器进入ESTABLISHED状态,到此一个TCP连接就完成了。

  • 三次握手用于请求客户端和服务端连接,发生在客户端发起 connect 和服务端使用 accept 接收

在这里插入图片描述

四次挥手
  • 四次挥手,即TCP连接的释放过程,是指终止TCP连接协议时,需要在客户端和服务器之间发送四个包,以确保双方都能正常且有序地关闭连接。以下是四次挥手的详细过程:

    • 第一次挥手:客户端发送一个FIN报文段给服务器,表示客户端要关闭到服务器的数据传送,客户端进入FIN_WAIT_1状态。

    • 第二次挥手:服务器收到FIN报文段后,发送一个ACK报文段给客户端,确认收到客户端的关闭请求,服务器进入CLOSE_WAIT状态。此时,TCP连接处于半关闭状态,即客户端到服务器的连接关闭,但服务器到客户端的连接仍然打开。

    • 第三次挥手:服务器发送一个FIN报文段给客户端,表示服务器也要关闭到客户端的数据传送,服务器进入LAST_ACK状态。

    • 第四次挥手:客户端收到FIN报文段后,进入TIME_WAIT状态,并发送一个ACK报文段给服务器,确认收到服务器的关闭请求,服务器进入CLOSED状态,完成四次挥手。

      此时,TCP连接同时完全关闭,双方都不能再发送数据。

  • 需要注意的是,在第二次挥手和第三次挥手之间,双方都会进行确认操作,以确保数据已经完全发送和接收。此外,在第三次挥手后,服务器仍然可以向客户端发送数据,直到收到客户端的ACK报文段为止。

  • 四次挥手的目的是确保TCP连接的可靠关闭,避免数据丢失或连接状态不一致等问题。通过四次挥手,客户端和服务器可以有序地关闭连接,释放资源,为下一次连接做好准备。

TCP

在这里插入图片描述

//客户端#include "head.h"
//   名       IP      端口号
//./cfd   127.0.0.1   10000
int main(int argc,char *argv[])
{//创建套接字文件//IPV4,TCP,0int cfd = socket(AF_INET,SOCK_STREAM,0);if(cfd == -1){printf("sfd socket fail \n");return -1;}//申请连接 struct sockaddr_in addr;      //通过参数 获取地址,端口addr.sin_family = AF_INET;     //地址族 IPV4addr.sin_port = atoi(argv[2]); //端口号//IPV4地址int res = inet_pton(AF_INET,argv[1],(struct in_addr*)&addr.sin_addr);if(res < 1){printf("pton fail");close(cfd);return 0;}res = connect(cfd,(struct sockaddr*)&addr,sizeof(addr));if(res < 0){printf("bind fail");close(cfd);return 0;}printf("cfd success \n");//发送数据char data[100];while(1){bzero(data,0);fputs("input:",stdout);fgets(data,sizeof(data),stdin);send(cfd,data,sizeof(data),0);if(strstr(data,"#") != NULL ){close(cfd);fputs("quit\n",stdout);break;}}close(cfd);printf("close \n");return 0;
}
//服务端#include "head.h"
//   名       IP      端口号
//./sfd   127.0.0.1   10000
int main(int argc,char *argv[])
{//创建套接字文件//IPV4,TCP,0int sfd = socket(AF_INET,SOCK_STREAM,0);if(sfd == -1){printf("sfd socket fail \n");return -1;}//绑定IP地址和端口号       struct sockaddr_in addr;addr.sin_family = AF_INET;     //addr.sin_port = atoi(argv[2]); //端口号//IPV4地址int  res  = inet_pton(AF_INET,argv[1],(struct in_addr*)&addr.sin_addr);if(res < 1){printf("pton fail");close(sfd);return 0;}//绑定套接字和网络地址+res = bind(sfd,(struct sockaddr*)&addr,sizeof(addr));if(res < 0){printf("bind fail");close(sfd);return 0;}  //监听套接字res = listen(sfd,6);if(res < 0){printf("listen fail");close(sfd);return 0;}//等待连接struct sockaddr_in c_addr;int len = sizeof(c_addr);int cfd_addr = accept(sfd,(struct sockaddr*)&c_addr,&len);//返回if(cfd_addr < 0){printf("accrpt fail");close(sfd);return 0;}printf("success \n");char data[100];while(1){bzero(data,0);recv(cfd_addr,data,sizeof(data),0);if(strstr(data,"#") != NULL){close(sfd);printf("退出 \n");break;}printf("the str: %s \n",data);}printf("close \n");return 0;
}

UDP

在这里插入图片描述

//cfd.c  客户端
#include "head.h"
//   名      端口号   
//./cfd      10000     
int main(int argc,char *argv[])
{	//创建套接字文件//IPV4,UDP,0int cfd = socket(AF_INET,SOCK_DGRAM,0);if(cfd == -1){printf("cfd socket fail \n");return -1;}		//绑定IP地址和端口号,就是当前的使用的IP       struct sockaddr_in cfd_addr;cfd_addr.sin_family = AF_INET;     //IPV4cfd_addr.sin_port = atoi(argv[1]); //端口号int ret = inet_pton(AF_INET, argv[1], (struct in_addr*)&cfd_addr.sin_addr);//绑定指定IP	int cfd_len = sizeof(cfd_addr);/*res = bind(cfd,(struct sockaddr*)&cfd_addr,sizeof(cfd_addr));*/	char buf[100];while(1){bzero(buf, sizeof(buf));fgets(buf,sizeof(buf),stdin);sendto(cfd, buf, sizeof(buf) - 1, 0,(struct sockaddr*)&cfd_addr,cfd_len);if (strstr(buf, "quit")  != NULL){break;}printf("from client[%d] data: %s\n", cfd, buf);}close(cfd);return 0;
}
//sfd.c#include "head.h"
//   名      端口号   
//./sfd      10000     
int main(int argc,char *argv[])
{//创建套接字文件//IPV4,UDP,0int sfd = socket(AF_INET,SOCK_DGRAM,0);if(sfd == -1){printf("sfd socket fail \n");return -1;}	 //绑定IP地址和端口号       struct sockaddr_in sfd_addr;sfd_addr.sin_family = AF_INET;     //IPV4sfd_addr.sin_port = atoi(argv[1]); //端口号sfd_addr.sin_addr.s_addr = htonl(INADDR_ANY);  //绑定所有IP地址bind(sfd,(struct sockaddr*)&sfd_addr,sizeof(sfd_addr));struct sockaddr cfd_addr;    //目标的地址int cfd_len = sizeof(cfd_addr);char buf[100];while(1){bzero(buf, sizeof(buf));recvfrom(sfd, buf, sizeof(buf) - 1, 0,(struct sockaddr*)&cfd_addr,&cfd_len);if (strstr(buf, "quit")  != NULL){break;}		printf("from client[%d] data: %s\n", sfd, buf);}	 close(sfd); return 0;
}

IO通信模式

  • 阻塞:read recv recvfrom 默认是阻塞模式,accept 也会阻塞

  • 非阻塞

    • fcntl :将文件描述符改成非阻塞模式
//获取原属性
int sta = fcntl(fd,F_GETFL);
//修改属性为非阻塞
sta |= O_NONBLOCK;
//重新设置属性
fcntl(fd,F_GETFL,sta);
  • 如果将accept 传入非阻塞的套接字文件,将只执行一次,这样会获取不到信息

  • 阻塞模式消耗CPU小于非阻塞模式

信号IO驱动

  • 等待数据不在阻塞,通过信号通知的方式触发数据读取操作,没有信号时不会进行无限判断
  • 通过signal 函数注册IO信号,在有数据时自动执行接收,反应快
  • 在多线程客户端服务端之间,使用多线程时使用

IP地址

  • 点分式,32位的IPV4

  • 127.0.0.1是回环地址,代表所有IP

    • 广播IP地址:最后一个字节是255,本地广播信息不会被路由器转发,转发是需要指明接收者的端口号
    • 组播(多播):使用D类IP地址(只要符合D类地址的规则),同一网络业务的主机一起分组,数据只发给同组用户
    • 广播在局域网进行,组播在广域网进行
  • A类:网络ID占 7位 ,最高位是固定的0;3个字节主机ID,

    • 范围:0.0.0.0 ~127.255.255.255,127.0.0.1 是一个回环地址
    • 一般用于大型网络,可以提供最大的主机数 2^24
  • B类:网络ID占 14 位;前两位固定为 1 0 , 2个字节主机ID,

    • 范围:128.0.0.0 ~ 191.255.255.255固定开头四位 1110
    • 一般用于中型 ,最大主机数 2^16
  • C类:网络占21位,前三位固定为 1 1 0 ; 1 个字节主机ID

    • 范围:192.0.0.0 ~223.255.255.255
    • 用于小型,最多主机数 2^8
  • D类:组播地址,(组IP),多点传送IP地址,固定开头四位 1110

    • 范围:224.0.0.0 ~ 239.255.255.255
    • 用于多播(组播),将信息发送给一组主机,因为没主机
  • E类:固定开头四位 1111 ,剩下保留

    • 范围:240.0.0.0 ~ 255.255.255.255
    • 用于实验室测试

接收超时

void *fun1(void *arg)
{int i = 0 ;while(1){printf("%d \n",i++);sleep(1);}
}void fun2(int sig)
{printf("manbao out");
}main()//./sfd 127.0.0.1 10005
{//创建线程pthread_t tid;if( pthread_create(&tid,NULL,fun1,NULL) != 0){perror();}  pthread_detach(tid);#if 0   //SIGALRM//注册信号signal(SIGALRM,fun2);   
#endif//创建套接字int sfd = socket(AF_INET,SOCK_STREAM,0);if(sfd < 0);  //绑定IP地址和端口号       struct sockaddr_in sfd_addr;addr.sin_family = AF_INET;     //addr.sin_port = atoi(argv[2]); //端口号//IPV4地址int  res  = inet_pton(AF_INET,argv[1],(struct in_addr*)&sfd_addr.sin_addr);if(res < 1)res = bind(sfd,(struct sockaddr*)&sfd_addr,sizeof(sfd_addr));if(res < 0)//监听listen(sfd,5);//获得发送方信息struct sockaddr_in cfd_addr;int cfd_len = sizeof(cfd_addr);int cfd = accept(sfd,(struct sockaddr)&cfd_addr,&cfd_len);//保存信息char cfd_ip[100];int cfd_port = ntoh(cfd_addr.sin_port);inet_ntops(AF_INET,&cfd_addr.sin_addr,cfd_ip,sizeof(cfd_ip));//取出IP地址printf("客户端ip:[%s],客户端端口号:[%d]",cfd_ip,cfd_port);
#if 1//设置超时时间struct timeval timeout;timeout.tv_sec = 5;timeout.tv_usec = 0;//设置超时,判断套接字是否超时setsockopt(cfd,SOL_SOCKET,SO_RCVTIMEO,&timeout,sizeof(timeout));
#enndif//接收char buf[256];while(1){
#if 0alarm(5);//设置5秒闹钟,到期后触发闹钟//触发一次后阻塞在接收上
#endif        //recv(cfd_addr,data,sizeof(data),0);int res = read(cfd,buf,sizeof(buf));if(res < 0){if(error == EAGAIN){printf("超时 %d waiting",timeout.tv_sec);continue;}else{perror("read error");break;}}else if(res == 0){printf("断开");break;}else{if(strstr(data,"#") != NULL){close(sfd);printf("退出 \n");break;}printf("the str: %s \n",data);}        }close(sfd);close(cfd);
}

多路复用

  • 网络IO模型:阻塞,非阻塞,信号IO,多路复用,异步IO
  • 一个线程管理多个IO事件,多个文件描述符,用于解决传统阻塞IO导致的线程资源浪费
  • select : 最早的多路复用,通过文件描述符集合统一监听多个文件描述符,一般不超过1024个文件,每次都要检查全部集合的就绪事件
  • poll : 优化了select 的最大固定大小的问题,改用动态数组保存文件描述符,但是每次还是需要遍历全部
  • epoll : 这是最优解,通过红黑树存储监听的文件描述符,就绪时直接返回事件,无需遍历,支持高并发
http://www.dtcms.com/a/577799.html

相关文章:

  • 专业做网站报价安徽网站建设系统
  • 网站建设对产品推销作用大吗wordpress主题购物
  • 基于SpringMVC的在线文档管理系统3yy4cg58(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
  • Qt中使用系统级全局热键
  • 零基础新手小白快速了解掌握服务集群与自动化运维(十八)监控模块--Zabbix监控--Rocky9基于MySQL安装Zabbix7
  • pc微信ccd 3.55算法。
  • DeepSpeed 分布式训练
  • 昭和仙君(五十七)标签票据模板渲染技术——东方仙盟筑基期
  • QScrollArea技术详解:构建流畅滚动体验
  • 基础数据结构之链表的反转链表:反转整个链表(leecode 206题 简单题)
  • 广东省网站集约化建设方案建设网站需要哪个软件
  • 网站开发技术视频教程wordpress添加菜单分类目录是灰的
  • 一种双重形式化表征方法:为人工智能与人类智慧的协同进化提供了全新的方法论基础
  • ETCD 权限配置
  • 数据结构(c++版):深入理解哈希表
  • HIKVISION前端一面面经整理
  • Rocky9基于MySQL安装Zabbix7
  • 安庆网站制作1688阿里巴巴国际站首页
  • 阿里云微服务引擎 MSE 及 API 网关 2025 年 10 月产品动态
  • 太原网站建设内蒙古建设工程造价信息网官网中项网
  • Oracle 19C RAC下TRUNCATE TABLE的REUSE STORAGE选项作用和风险浅析!
  • CentOS 7 Oracle 11g RAC+DataGuard 分阶段静默部署脚本
  • 索牛网站建设江苏省建设厅官网网站首页
  • 三网合一网站系统晋城市网站建设
  • 智慧幼儿园管理系统-幼儿园多园区管理小程序的技术架构与应用实践:重构幼教领域数字化管理范式-幼儿园小程序开发-幼儿园软件开发-幼儿园系统开发定制
  • 精准招聘新纪元:AI 重构选才逻辑
  • 超聚变联手英特尔打造边缘智算一体机,重构工作站市场格局
  • 英国服务器Windows系统远程桌面安装与优化
  • 青岛做网站优化大屏网站模板
  • 多项分布 (Multinomial Distribution)