Python——Scoket编程

Python——Socket编程

参考博文:https://www.cnblogs.com/linhaifeng/articles/6129246.html
网络基础参考博文:https://www.cnblogs.com/linhaifeng/articles/5937962.html

一、什么是Scoket?

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

二、套接字

1、套接字发展史

题外话:进程跟进程之间是无法通信的;套接字的发展就是解决此问题。
在这里插入图片描述

2、两种类型的套接字

在这里插入图片描述
AF是Address Family 的缩写,意为地址家族。

此次只关心 AF_INET 网络编程使用。

4、TCP套接字工作流程

在这里插入图片描述
基于上面的流程,来举个简单的通信例子:

先来看下服务端的代码:

在这里插入图片描述

接着是客户端的代码:
在这里插入图片描述

5、三次握手与四次挥手

简略图解:
在这里插入图片描述注意:主动断开链接的不一定是客户端
可以通过实验,链接百度,会发觉主动断开的是服务端。因为在大并发的情况下,服务端不会保留你客户端的链接,多保留一分钟会多占用一分钟资源(为了节省资源)。

为什么握手是三次,挥手是四次?
因为握手是建立消息通道;而挥手是断开消息通道,谁数据发完了谁发起断开的请求,回应了发来的消息后,还要再发送一次断开链接的请求

如果还不懂,百度其他文章,理解三次握手与四次挥手。

6、半链接池

半链接意为:一整个链接没有建立成功都是半链接。
backlog:半链接池

服务端可能同时接受到很多客户端的涌进,太多则响应不过来。所以把客户端的接入都放在backlog里,服务端从backlog里取出链接来进行回应。超出backlog的容量都要排队。

对应到程序当中的位置就是:
在这里插入图片描述

7、TCP客户端服务端循环发消息

服务端代码:
在这里插入图片描述

客户端代码:
在这里插入图片描述

8、socket收发消息原理

上面代码中,如果发个空 “ ”(回车,不是空格),程序则会卡主。为什么会卡主呢?先看下面:
在这里插入图片描述
内存分为用户态和内核态。应用程序属于用户态内存。操作系统属于内核态内存。发消息会从用户态内存发到内核态内存,再由操作系统接收,操作系统再操作网卡发送。另一边网卡接收后又交给操作系统,操作系统再给内核态内存,后面步骤依旧。recv(1024)是工作在socket应用程序里;1024是从内核态内存里取出的。send()发送也是发到内核态内内存。

之所以“空”没有反应,是因为客户端发送“空”到内核态内存,内核态内存则会什么都没接收到,既然没有接收到,也不会发送到服务端。所以此时卡主是因为客户端自己的内核态缓存里没东西,服务端的内核态内存什么都没有接收到,所以卡主。

解决“空”问题:
在这里插入图片描述

加这一句话就能解决

9、TCP服务端循环链接请求收发消息

服务端与客户端不可能通话一次就挂断,应该是服务端一直挂着,来了客户端就通话,客户端挂断,服务端就继续等下一个客户端。所以在等待客户端连接前加一个循环就能解决:
在这里插入图片描述

服务端客户端都在正常运行,如果客户端突然非正常关闭,服务端会抛出异常:
在这里插入图片描述
解决这种问题,用一个异常处理就可以解决:
在这里插入图片描述

10、基于TCP实现远程命令(类似于xshell)

小练习:客户端发送命令,服务端接收命令并执行,把执行后的结果返回客户端

先来学习一个模块:

subprocess.Popen('dir',shell = True)   # 用shell工具解释前面的命令

再学习一个概念:两个程序间是无法通信的,需要通过一个介质来进行通信,这个介质就是管道,我们可以控制这个管道。

stdout  #标准输出
stdin	#标准输入
stderr	#标准错误输出,有错误时不会在stdout里,在stderr里

举个例子:
当你输出什么东西显示在屏幕上时(就像是Linux的命令行,你打什么东西就会立即显示出来),也属于两个程序间的通信,屏幕是一个程序。这时可以控制管道,先把内容扔进管道里,需要的时候再把东西从管道里拿出来。

所以

subprocess.Popen('dir',shell = True,stdout = subprocess.PIPE)   # PIPE是管子的意思。代表把输出结果交给管道

所以类似的效果是:
在这里插入图片描述
所以最终服务端代码:
在这里插入图片描述
客户端代码:
在这里插入图片描述

11、总结TCP套接字

TCP服务端流程:
在这里插入图片描述
TCP客户端流程:
在这里插入图片描述

12、注意

有时把程序关了,端口也不会立马释放。

在这里插入图片描述方法一:
在这里插入图片描述
方法二:
在这里插入图片描述
此方法不细讲,有兴趣的自己去搜。

三、基于UDP的套接字

1、UDP套接字流程:

服务端:
在这里插入图片描述
客户端:
在这里插入图片描述
可以发现,代码部分少了listen(),listen是用来挂起链接请求,等待链接的建立。UDP根本没有链接一说,所以就没有listen。

实例:
服务端:
在这里插入图片描述
客户端:
在这里插入图片描述
UDP的接收是recvfrom,收的是一个元组的形式

2、recv与recvfrom的区别

在讲区别之前,先讲一下,通过实验可以发现,UDP的服务端可以对多个客户端通信;而TCP不行,服务端需要与这个客户端断开链接后,才能与下一个客户端通信。
为什么UDP可以?因为UDP不用建立链接

可以实验发现,UDP发送“空”,能发的出去,服务端也能接收,其原因是:

四、粘包现象

1、粘包现象

注意:这里的代码用的是 基于TCP实现远程命令 里的代码

当我们输入 dir 时,可看到
在这里插入图片描述显示的是当前路径下的文件

输入ipconfig 时,查看ip相关信息:
在这里插入图片描述
这时,如果再输入 dir ,查看当前路径文件的信息时,就会发生奇怪的事:
在这里插入图片描述
可以看到,这里明明输入 dir ,显示的还是 ipconfig 的信息,这种现象就是粘包现象
上一次还没收完的信息,这一次继续接收。原因在于缓冲区不够大。就是下面这个设置:
在这里插入图片描述

只有TCP有粘包现象,UDP没有。 UDP中,如果上一次信息没有接收完,就会直接扔掉。

不同平台显示的结果不一样,下面是UDP在Windows中的异常:
在这里插入图片描述题外话:UDP哪怕只有客户端,也可以执行程序,当然最终结果是卡主。因为能发出去,但是没有接收信息,最终就是卡主。所以说UDP是不可靠传输,只管发,不管收。

2、什么是粘包

在这里插入图片描述在这里插入图片描述g.csdnimg.cn/20210107200144875.png)
在这里插入图片描述

五、socketserver实现并发

1、socketserver模块实现并发效果

通过导入socketserver模块实现并发:

服务端代码:
在这里插入图片描述
客户端代码:
在这里插入图片描述
在这里插入图片描述
两个客户端发送,服务端都能接收

2、socketserver模块

两大类:
server 类:处理链接
在这里插入图片描述在这里插入图片描述

request 类:处理通信

在这里插入图片描述

进到模块内部查看代码,可以发现里面有很多的类,其中也有互相继承,看下图:
在这里插入图片描述
它们的相互继承关系:

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

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

3、socketserver源码分析tcp版本

自己看源码去理解!

4、socketserver源码分析udp版本

自己看源码去理解!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值