Linux网络编程02

news2024/9/27 17:33:20

UDP协议

UDP协议处于传输层,是不可靠谱、无连接、消息有边界的协议
TCP类似于管道,UDP类似于队列

UDP头部
传输层头部都不需要IP地址,都只需要端口号
在这里插入图片描述

Berkeley Socket(库)

Berkeley Scoket 库已经完成了传输层之下的内容,我们只需要再应用层调用下面提供的服务接口即可

Socket :套接字,建立连接时使用

地址:链路层使用MAC地址、网络层使用IP地址、传输层使用端口号
引用层的地址:IP地址加上端口号

IPv4的地址格式
在这里插入图片描述
sin_family:地址的类型AF_INET代表IPv4
sin_port:端口号(使用网络字节序)16Byte(2字节)
sin_addr:IP地址(使用网络字节序)32Byte(4字节)

网络字节序
大端法存储数据被称为网络字节序
大小端都可以存储数据的为主机字节序
在这里插入图片描述
数据如果要从主机到网络,那么我们就要将小端数据变成大端数据

在这里插入图片描述
h host主机
n net网络
s short 2B 16bit
l int 4B 32bit

大小端转换
我们要用printf()就使用端;如果我们使用sockaddr就使用大端
在这里插入图片描述

在这里插入图片描述

const char *cp:点分十进制
struct in_addr *inp:存储结果的地址
inet_aton(const char * cp ,struct in_addr * np):点分十进制—>32位大端整数,结果作为参数
inet_addr:点分十进制—>32位大端整数,结果作为返回值

char *inet_ntoa:把32位大端整数转换为字符串

IP地址实现大小端转换
在这里插入图片描述

IP地址以及端口实现大小端转换
在这里插入图片描述

可以使用sudo cat /etc/hosts查看本地存在的域名映射

从代码中获取域名对应的IP地址
在这里插入图片描述
底层使用了DNS服务器,断网的时候会报错,这个函数出错了不能用perror,报错返回空指针
可以根据这个函数获取主机信息
在这里插入图片描述

使用gethostbyname获取远程目标主机的信息
在这里插入图片描述

可以将IPv4或者IPv6转换位字符串
在这里插入图片描述

基于TCP的网络通信
网络的用法和文件是一样的
在这里插入图片描述

socket(系统调用)

创建一个用于网络传输的文件对象
在这里插入图片描述

domain:指的是你所使用的领域,一般使用AF_INET表示IPv4
在这里插入图片描述
type:
在这里插入图片描述
SOCK_STREAM:TCP协议
SOCK_DGRAM:UDP协议
protocol:填0表示自动获取

connect
建立连接,发送第一次握手

在这里插入图片描述
sockfd:填的值是socket的返回值
addr 和addrlen描述目标地址

Linux上使用抓包操作查看自己发送的数据包
tcpdump -i 网卡名称 port 端口号
在这里插入图片描述

tcp的标志
根据四元组<源IP,源端口号,目的IP,目的端口>来区分两条不同的TCP连接,只要四元组中有一个不一样那就是不同的TCP连接

服务端的IP和端口一般是固定的—>这不影响并发连接数量的上限

bind(服务端)
让服务端端绑定一个IP:port给socket ,以便于客户端每次都可以固定的和同一个端口连接服务端

在这里插入图片描述
绑定端口之后客户端还不能连接服务端,还需要让服务端调用listen系统调用

listen(服务端调用)
listen是说明让socket当作服务端来使用
服务端调用listen之后客户端才能connect
listen会把socket文件对象清空,会重新组织成两个数据结构,一个是半连接队列,一个是全连接队列
当服务端调用listen,接收到客户端的connect请求,服务端会像客户端发回ACK应答,此时这个客户端就会进入如半连接队列里面,当客户端完成了三次握手的最后一个ACK是服务端就会把这个连接放入连接队列里面

在这里插入图片描述
backlog:半连接队列的长度

DDOS攻击
SYN flood 泛洪
客户端你只对服务器只发送第一次握手,但是不发生送第三次握手,方客户端越来越多的时候服务器端的半连接队列就会被充满,以至于服务器无法在继续连接真难正需要连接的客户端
如何防御DDOS攻击?
(1)增发半连接队列(不可取)
(2)使用SYN cookies

accept
上面我们已经了解到我们可以使用socket为客户端创建一个用于网络连接的文件,对于服务端首先会使用bind为客户端绑定固定端口,然后再利用listen改造客户端的socket文件对象,建立连接之后便会把客户端建立的连接放入全连接队列。
接下来调用accept从全连接队列取出一个连接,根据这个连接创建一个已链接socket
因此就会有两个文件描述符一个是socketFd(用于建立连接),一个是netFd(用于发送数据)
accept的本质是一个read,如果全连接队列为空,accept就会阻塞,当全连接队列不为空就会停止阻塞

在这里插入图片描述
sockfd:listen 的 fd
addr:addr填本地地址,如果填了本地地址就可以获取对端地址,如果不想获取对端地址就填NULL
addrlen:先申请一个socklen_t的变量,再取地址传递,因为他是一个传入传出参数,并且socklen_t的长度不能嫩能够填0,要填addr的长度

读写网络缓冲区
write/read 可以用于客户端的socket以及服务端端的已连接socket,不可以用于listensocket
send和recv只能操作socket
write和read可以操作文件和socket以及管道等

send和write
在这里插入图片描述
flages:控制send的行为,如果为0,不做任何行为
在对socket操作时 send(… , 0)和write是等价的
send/write不是往网络中发数据,其本质是拷贝数据到SND(发送)缓冲区,发不发送由内核协议栈决定是否发向网络

read和recv
在这里插入图片描述
read/recv是拷贝数据从RCV缓冲区到用户空间,网络中如果没有数据就会发生阻塞

使用socket实现网络连接

在这里插入图片描述
在这里插入图片描述

如何使接收方和发送方知道相同的信息,就需要在应用层制定协议

利用socket实现即时聊天

基本 上和管道时一样的,socket的R,W的fd是同一个
使用IO多路复用来防止stdin阻塞
在这里插入图片描述

在这里插入图片描述

TIME_WAIT

主动关闭方在四次挥手之后会进入TIME_WAIT状态
服务端如果主动关闭,会进入TIME_WAIT(固定60S),服务端在time_wait状态,不允许bind同样的IP端口,避免在这个时间之内他们两方在建立新的连接,但是旧连接的数据可能就会在新连接里传输
但是每次客户端发起新的连接都是从不同的端口进行发出,因此每次发起连接的四元组都是不一样的,因此我们没有必要让服务端进入TIME_WAIT

让服务端你无视TIME_WAIT
修改socket的属性(在bind之前修改)

使用setsockopt修改socket的属性
在这里插入图片描述

sockfd:listen socket,监听描述符 level
:直接填SOL_SOCKET,表示修改的是socket这一层(传输层) optname:要修改哪个属性
在这里插入图片描述

optval:要改成什么样 optlen:属性的长度

在这里插入图片描述
服务端不是屏蔽TIME_WAIT而只是忽略TIME_WAIT

实现断线重连

服务端使用select监听sockfd—>读事件,如果都就绪,说明调用accept不会阻塞

  #include <43func.h>
   //服务端
   int main(int argc,char * argv[]) {
       ARGS_CHECK(argc,3);
       int sockfd = socket(AF_INET,SOCK_STREAM,0);//创建你IPv4的TCP连接
       ERROR_CHECK(sockfd,-1,"socket");
       int optval = 1;
       int ret = setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(int));
       ERROR_CHECK(ret,-1,"setsockopt");
      struct sockaddr_in addr;
      addr.sin_family = AF_INET;
      addr.sin_port = htons(atoi(argv[2]));
      addr.sin_addr.s_addr = inet_addr(argv[1]);
      ret = bind(sockfd,(struct sockaddr*)&addr,sizeof(addr));
      ERROR_CHECK(ret,-1,"bind");
      ret = listen(sockfd,10);//更改server端socket的结构,更改半连接队列长度为10
      ERROR_CHECK(ret,-1,"listen");
      //accept要放在select后面
      //去使用时确保从标准输入中输入数据在客户端建立连接之后
      //accept之后创建新的netfd,这个netfd加入监听--->分离监听和就绪
      //客户端如果断开连接以后,服务端不要退出,要取消监听netfd
      fd_set rdset;//保存就绪的fd
      fd_set monitorSet;//使用一个单独的监听集合
      FD_ZERO(&monitorSet);//初始化rdset
      FD_SET(STDIN_FILENO,&monitorSet);//将文件输入流,添加到监听队列.防止阻塞
      char buf[4096] = {0};
      int netfd = -1;
      while(1) {
          memcpy(&rdset,&monitorSet,sizeof(fd_set));//初始化数组
          select(20,&rdset,NULL,NULL,NULL);//开启监听
          if(FD_ISSET(STDIN_FILENO,&rdset)){
              bzero(buf,sizeof(buf));//清空数组
              ret = read(STDIN_FILENO,buf,sizeof(buf));//读取输入流数据
              if(ret == 0) {
                  send(netfd,"nishigehaoren",13,0);
                  break;
              }
              send(netfd,buf,strlen(buf),0);//向网络文件中写入数据
          }
          if(FD_ISSET(sockfd,&rdset)){
              netfd = accept(sockfd,NULL,NULL);//创建socket文件对象
              ERROR_CHECK(netfd,-1,"accept");
              FD_SET(netfd,&monitorSet);//将netfd加入监听集合
              puts("new connect is accepted!\n");
          }
          if(FD_ISSET(netfd,&rdset)) {
              bzero(buf,sizeof(buf));//清空buf
              ret = read(netfd,buf,sizeof(buf));//读取网络文件中的数据
              if(ret == 0) {
                  puts("bye bye");
                  FD_CLR(netfd,&monitorSet);//将netfd取消监听
                  close(netfd);
                  netfd = -1;
                  continue;
              }
              puts(buf);
          }
      }
      close(sockfd);
      close(netfd);
  }

在这里插入图片描述

实现群聊
在这里插入图片描述
在这里插入图片描述

UDP实现聊天
在这里插入图片描述
bind:固定服务端的IP:port
sendto:客户端先sendto

UPD中socket的用法
client
在这里插入图片描述
server
在这里插入图片描述

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

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

相关文章

【Xilinx Kintex-7 Virtex-7 LVDS bank电压】

各种介绍很多&#xff0c;也都写的似乎很长很详细&#xff0c;但有错误。 详细的查阅Xilinx 论坛 43989 核心 总结一下就是Xilinx 7serious 的FPGA ,你如果要配置成LVDS,这的LVDS是正儿八经的那种&#xff0c;那么FPGA 这块你只需要记住两点就可以。 第一&#xff0c;假如你…

docker-compose 简单部署Flask + Redis + Nginx环境搭建网站

主博客目录&#xff1a;《从零开始学习搭建量化平台笔记》 主项目计划需要搭建一个 Flask Redis Nginx环境 来制作一个可视化的网站&#xff0c;为了避免搭完就忘&#xff0c;因此就有了这个博客。 任务&#xff1a;搭建一个内网通信且只有由Nginx代理发放的网页端显示环境。…

Unity多人同时在线海量玩家角色的架构与设计

前言 Unity多人同时在线的游戏会有很大的地图&#xff0c;大量的玩家同时在线,以及玩家会有不同的游戏职业&#xff0c;这样众多的玩家游戏角色我们客户端应该如何来设计呢&#xff1f;本文来分享以下几个点 对惹&#xff0c;这里有一个游戏开发交流小组&#xff0c;希望大家…

腾讯待办小程序关停怎么办?可替代的智能待办提醒工具

有不少小伙伴在选择待办提醒工具时&#xff0c;会使用微信中的腾讯待办小程序&#xff0c;在里面逐条记录待办事项、设置定时提醒&#xff0c;然后通过微信接收待办提醒。 不过最近一段时间&#xff0c;使用腾讯待办的用户都发现了“业务关停通知”的弹窗&#xff0c;确实如此…

代码随想录打卡第五十五天|● 300.最长递增子序列 ● 674. 最长连续递增序列 ● 718. 最长重复子数组

300.最长递增子序列 **题目&#xff1a;**给你一个整数数组 nums &#xff0c;找到其中最长严格递增子序列的长度。子序列 是由数组派生而来的序列&#xff0c;删除&#xff08;或不删除&#xff09;数组中的元素而不改变其余元素的顺序。例如&#xff0c;[3,6,2,7] 是数组 [0…

高数笔记04:微分方程与多元函数微分学

图源&#xff1a;文心一言 时间比较紧张&#xff0c;仅导图~~&#x1f95d;&#x1f95d; 第1版&#xff1a;查资料、画导图~&#x1f9e9;&#x1f9e9; 参考资料&#xff1a;《高等数学 基础篇》武忠祥 &#x1f9ae;思维导图 &#x1f636;‍&#x1f32b;️思维导图为整…

1.面向对象——继承

继承 子类拥有父类非 private 的属性、方法。 子类可以拥有自己的属性和方法&#xff0c;即子类可以对父类进行扩展。 子类可以用自己的方式实现父类的方法。 提高了类之间的耦合性&#xff08;继承的缺点&#xff0c;耦合度高就会造成代码之间的联系越紧密&#xff0c;代码…

强化学习------DDQN算法

前言 DQN算法 DQN算法有一个显著的问题&#xff0c;就是DQN估计的Q值往往会偏大。这是由于我们Q值是以下一个s’的Q值的最大值来估算的&#xff0c;但下一个state的Q值也是一个估算值&#xff0c;也依赖它的下一个state的Q值…&#xff0c;这就导致了Q值往往会有偏大的的情况…

antd+全屏的坑(全屏下a-modal/下拉框等不展示)

问题&#xff1a;针对某个元素全屏时&#xff0c;下拉框/弹窗/二次确认窗不展示&#xff1a;下拉框是往body里面插入的&#xff0c;全屏的元素盖住了下拉框。解决&#xff1a;给有下拉框的加入:append-to-body"false"&#xff08;缺点&#xff1a;每个都需要加&#…

k8s的概念

概念 它是一种开源的容器编排平台&#xff0c;用于自动化部署&#xff0c;扩展和管理容器化的应用程序&#xff0c;它提供了一种容器编排和管理的方式&#xff0c;可以帮助开发人员更轻松地管理容器化的的应用程序&#xff0c;并且提供了一种跨多个主机的自动化部署和管理机制…

为什么看了那么多测试技术帖,感觉自己还是菜?

作为测试新手&#xff0c;最爱莫过于看各大牛发的技术贴&#xff0c;这篇很牛叉&#xff0c;那篇也很有道理&#xff0c;似乎自己看着看着也会成为高手。然而几年后&#xff0c;发现自己对专业知识的理解乱的很&#xff0c;里面更有很多自相矛盾的地方&#xff0c;这到底是哪里…

PFAF-Net

I 1 _1 1​和I 2 _2 2​是多模态图像&#xff0c;I F _F F​是融合图像。FT 1 _1 1​是基于空间注意力的融合&#xff0c;FT 2 _2 2​是基于通道注意力的融合 作者未提供代码

Spring及SpringBoot中AOP的使用

Spring中AOP示例 <dependencies><!--Spring核心包--><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>5.3.6</version></dependency><!--引入SpringBean--&…

Java工具库——commons-lang3的50个常用方法

未来的你&#xff0c;我亲爱的女孩&#xff0c;愿此刻无忧无虑&#xff0c;开心&#xff0c;快乐… 工具库介绍 Apache Commons Lang 3&#xff08;通常简称为Commons Lang 3&#xff09;是Apache Commons项目中的一个Java工具库&#xff0c;它提供了一系列实用的工具类和方法…

3.6每日一题(线性方程求通解)

1、判断类型选择方法&#xff1a;发现以y为未知函数&#xff0c;以x为自变量&#xff0c;不符合我们学过的类型 2、此时有两种方法&#xff1a; &#xff08;1&#xff09;x 与 y 对调&#xff0c;此时 x 为未知函数&#xff0c;y 为自变量 &#xff08;2&#xff09;变量代换…

【Mybatis-Plus】常见的@table类注解

目录 引入Mybatis-Plus依赖 TableName 当实体类的类名在转成小写后和数据库表名相同时 当实体类的类名在转成小写后和数据库表名不相同时 Tableld TableField 当数据库字段名与实体类成员不一致 成员变量名以is开头&#xff0c;且是布尔值 ​编辑 成员变量名与数据库关…

轻量级 IDE 文本编辑器 Geany 发布 2.0

Geany 是功能强大、稳定、轻量的开发者专用文本编辑器&#xff0c;支持 Linux、Windows 和 macOS&#xff0c;内置支持 50 多种编程语言。 2005 年Geany 发布首个版本 0.1。上周四刚好是 Geany 诞生 18 周年纪念日&#xff0c;官方发布了 2.0 正式版以表庆祝。 下载地址&#…

小红书app拉新上线了 适合网推社群和校园渠道作业

小红书app签到拉新上线了可以通过“聚量推客”进行申请&#xff0c;下面大概是要求和流程 要求网推社群渠道或者地推校园渠道&#xff0c;其它类型渠道禁止

R语言绘图-5-条形图(修改坐标轴以及图例等)

0. 说明&#xff1a; 1. 绘制条形图&#xff1b; 2. 添加文本并调整位置&#xff1b; 3. 调整x轴刻度的字体、角度及颜色&#xff1b; 4. 在导出pdf时&#xff0c;如果没有字体&#xff0c;该怎么解决问题&#xff1b; 1. 结果&#xff1a; 2. 代码&#xff1a; library(ggp…

sql--索引使用 ---覆盖索引

覆盖索引 Select 后接 * 走id索引才是最优&#xff0c;使用二级索引则需要回表&#xff08;性能稍差&#xff09; 前缀索引 Create index 索引名 on 表名( 字段名( n ) ) n数字 n代表提取这个字符串的n个构建索引 &#xff1f;&#xff1f;那么 n 为几性能是最好的呢&…