python_20_socket
什么是socket?
-- 通过各种协议,发送和接收数据,实现网络通信
-- 在python3中,网络发送只能发二进制数据
OSI七层模型是什么?
应用
表示
会话
传输
网络 ip地址
数据链路 mac地址
物理层
什么是TCP和UDP协议?
-- TCP -- 面向连接,三次握手,4次断开
-- UDP -- 面向无连接
对于socket通信的两个通信端有哪些工作?
客户端:
-- 导入 socket
-- 声明协议 TCP
-- 连接(远程ip和端口)
-- 发送数据 send
-- 关闭 close
服务端:
-- 导入 socket
-- 声明协议 TCP
-- 绑定监听(ip,端口号)
-- 等待 accept()
-- 接收 recv()
- 发送 send
什么是地址簇?
-- .AF_UNIX -- unix本机进程进行通信
-- .AF_INET IPV4 -- ipv4
-- .AF_INET6 IPV6 -- ipv6
socket有哪些类型?
-- .SOCK_STREAM -- TCP
-- .SOCK_DGRAM -- UDP
-- .SOCK_RAM -- 修改和构造ip地址头,伪造ip地址
如何实现socket通信?
-- 不能发送空数据,服务器和客户端都需要对空数据进行判断,空数据来源于客户端输入空数据和服务器端出现错误
服务端:
import socket
server = socket.socket() # 声明协议,默认ipv4,tcp协议
server.bind(('localhost',6969)) # 绑定监听端口
server.listen(5) # 开始监听,最大支持5个挂起
con, addr = server.accept() # 获得监听实例和来源ip和端口
data = con.recv(1024) # 接收数据,1024是发送大小,最多8192,不准确
con.send(data.upper()) # 发送数据
server.close() # 关闭服务,理论上服务是永久运行下去的
客户端:
import socket
client = socket.socket() # 声明协议,返回对象
client.connect(('localhost',6969)) # 连接服务器
client.send(b'hello word!') # 发数据
data = client.recv(1024) # 收数据
client.close() # 关闭客户端
-- 以上只是实现了一次对话,如何实现客户端多次和服务端进行交互?
服务器端:
import socket
client = socket.socket() # 声明协议,返回对象
client.connect(('localhost',6969)) # 连接服务器
while True: # 循环接收一个客户端请求
client.send(b'hello word!') # 发数据
data = client.recv(1024) # 收数据
client.close() # 关闭客户端
客户端:
import socket
client = socket.socket()
client.connect(('localhost',6969))
while True: # 循环发
data_1 = input('>>>:').strip() # 用户输入
if len(data_1) == 0: # 输入为空时候,重新输入
continue
client.send(data_1.encode('utf-8'))
data = client.recv(1024)
print(data.decode('utf-8'))
client.close()
以上只实现了和一个客户端交互,如何和多个客户端进行交互?
服务器端:
import socket
server = socket.socket()
server.bind(('localhost',6969))
server.listen(5)
while True:
con, addr = server.accept()
while True:
try:
data = con.recv(1024)
except ConnectionResetError as e: # 远程连接断开异常
break
con.send(data.upper())
print(data)
server.close()
以上实现了和多个连接,但是多个客户端会进入排队状态
假如发送大数据,如何解决传送大数据和黏包问题?
服务器端
-- 先打开文件,读取进来
while True: # 进行下面步骤循环
-- 发送文件的大小 len(文件),整数不能encode,先str转换成字符串
-- 收到客户端的答应,发送数据一份数据
-- .sendall() --自动循环发送大文件
-- 接收客户端收完数据答应,准备发送下一份数据
客户端:
-- 接收到服务器发来的文件大小数据,返回一个数据说,我收到了
-- 循环进行接收(初始化空数据长度,然后大小与原数据进行比较)
黏包文件解决?
-- 最主要是最后一次收的时候,多收了
-- low方法1: time.sleep()
-- 高级方法2:
服务器端:
两个send之间加一个 client_ack = conn.recv(1024) 一种阻塞状态,接收客户端收完指令,确定客户端是否收完
客户端:
收完之后,返回指令给客户端
-- 高级方法3: --永远不可能黏包
服务器端:
只发送文件大小
客户端:
只接收文件大小的数据
如何做到?
while 收到文件大小 < 文件大小: # 确定把文件收完,至少多收1次
if 文件大小 – 收到文件大小 > 1024 # 大于1024至少收一次
size = 1024 # 动态接收
else:
size = 文件大小 – 收到文件大小 # 只接收剩余大小的文件
data = client.recv(size) # 通过上面的判断变成动态size
如何进行md5验证?
-- 只能验证二进制数据
服务器端:
import hashlib # 导入hash模块
import socket
server = socket.socket()
server.bind(('localhoust', 9999)) # 绑定端口
server.listen()
while True:
conn, addr = server.accept() # 等待连接
f = open('test.text','rb') # 打开文件
conn.send(str(len(f)).encode()) # 发送文件大小
data = conn.recv() # 等待收到确认提示
m = hashlib.md5() # 实例md5对象
for line in f: # 一行一行读文件
m.update(line) # 新加数据,进行md5值生成
conn.send(line) # 一行一行发
f.close()
conn.send(m.hexdigest().encode('utf-8')) # 发送最后文件的md5
ftp server
服务器端:
-- 读取文件名
-- 检查文件是否存在
-- 打开文件
-- 计算文件大小和md5值,并发送给客户端
-- 发送文件给客户端
-- 等待客户端确认
-- 开始边读边发
计算大小的坑:
中文计算:
>>> a = '嘻嘻'
>>> len(a)
2
>>> len(a.encode())
6
>>> len(a.encode('utf-8'))
6
中文字符串转换成bytes类型,utf-8中每个中文占用3个字节
什么是socketserver?
-- 一种更上层对socket的封装,简化socket程序编写
socketserver的框架是什么?
imoprt socketsever
class 处理请求类名a(socketserver.BaseRequestHandler):
# 继承socketserver中BaseRequestHandler基础类
def handle(self): # 重写BaseRequestHandler中handle方法
self.data = self.request.recv(1024) # 等待收数据
print(self.client_addr) # 打印clinet的ip地址和端口号
self.request.send(self.data.upper()) # 发送处理后的数据给客户端
if __name__ == ‘__main__’:
HOST, PORT = ‘IP地址’, 端口号 # 绑定监听端口
server = socketserver.TCPServer((HOST, PORT), 处理请求类名a)
server.server_forever() # 服务永久运行下去
如何进行多线程处理请求?
server = socketserver.TCPServer((HOST, PORT), 处理请求类名a)
改成:
server = socketserver. ThreadingTCPServer ((HOST, PORT), 处理请求类名a)
python_20_socket的更多相关文章
随机推荐
- 使用Docker搭建Jenkins+Docker持续集成环境(自动化构建发布部署)
本文介绍如何通过Jenkins的docker镜像从零开始构建一个基于docker镜像的持续集成环境,包含自动化构建.发布到仓库\并部署上线. 0. 前置条件 服务器安装docker,并启动docker ...
- golang动态加载原生代码思路
golang动态加载原生代码思路(非plugin,非so文件.使用mmap形式运行机器码,可释放) 1.用go tool objdump,可以看到任意函数的机器码.汇编指令.偏移.(go源码下面有一个 ...
- linux下使用 FreeRDP 连接 Windows 远程桌面(转)
这是一种最简单的使用方法,转载自http://wenzhixin.net.cn/2014/03/16/ubuntu_xfreerdp 简介 FreeRDP 是一款开源的远程桌面系统,支持多种平台, 在 ...
- HTTPS协议开通,Apache服务器CSR签名申请
登录您的服务器终端 (SSH). 在命令提示符下,键入以下命令: openssl req -new -newkey rsa:2048 -nodes -keyout yourdomain.key -ou ...
- JAVA进阶--ThreadPoolExecutor机制
ThreadPoolExecutor机制 一.概述 1.ThreadPoolExecutor作为java.util.concurrent包对外提供基础实现,以内部线程池的形式对外提供管理任务执行,线程 ...
- Mysql安装与主从配置
安装MySql 操作系统:Windows Server 2008 R2 Standard MySql版本:mysql-5.7.17-winx64 第一步:解压mysql-5.7.17-winx64.z ...
- Wannafly模拟赛 A.矩阵(二分答案+hash)
矩阵 时间限制:1秒 空间限制:131072K 题目描述 给出一个n * m的矩阵.让你从中发现一个最大的正方形.使得这样子的正方形在矩阵中出现了至少两次.输出最大正方形的边长. 输入描述: 第一行两 ...
- [51nod1254]最大子段和 V2
N个整数组成的序列a[1],a[2],a[3],-,a[n],你可以对数组中的一对元素进行交换,并且交换后求a[1]至a[n]的最大子段和,所能得到的结果是所有交换中最大的.当所给的整数均为负数时和为 ...
- C#中的多线程超时处理实践
最近我正在处理C#中关于timeout行为的一些bug.解决方案非常有意思,所以我在这里分享给广大博友们. 我要处理的是下面这些情况: 我们做了一个应用程序,程序中有这么一个模块,它的功能向用户显示一 ...
- Xshell无法连接到LINUX虚拟机
首先与遇到的情况是,在虚拟机下安装了Linux后,xshell无法连接远程的虚拟机. 我遇到的情况是虚拟机可以ping 主机,主机确ping不了虚拟机. 使用的VM设置了两个网卡,一个nat 一个h ...