今天没有很多概念性的东西,主要是方法性的东西以及编程的一些方法吧

今日份目录

1.UDP传输的特点以及实验

2.UTP与UDP传输的区别

3.基于tcp的low版带验证功能的FTP小程序

4.基于socketserver的多人聊天

5.验证客户端的完整性

6.socket的阻塞模型与非阻塞模型

开始今日份整理

1.UDP传输的特点以及实验

UDP与TCP都是传输层中的重要传输协议,下面说一下UDP的特点

1.1 UDP传输特点

无连接的,面向数据包,不可靠的,快速的,不需要accept/connect 也没有握手

1.2 基于UDP的多人聊天

#服务端
import socket sk = socket.socket(type=socket.SOCK_DGRAM)
sk.bind(('127.0.0.1',8500)) while True:
msg,addr = sk.recvfrom(1024)
print(msg.decode())
send_message = input('>>>').strip()
sk.sendto(send_message.encode(),(addr)) sk.close()
#客户端
import socket sk = socket.socket(type= socket.SOCK_DGRAM)
while True:
msg = input('>>>').strip()
send_msg ='test1:'+ msg
sk.sendto(send_msg.encode(),('127.0.0.1',8500))
msg,addr =sk.recvfrom(1024)
print(msg.decode()) sk.close()

多个

客户端只要多拷贝几份client代码就可以了,就会发现在服务器端出现很多用户发过来的信息,由于是在命令行界面,在input界面会阻塞,所以并不会马上看到多人发来的信息。在图形化界面就不会这样了

2.UTP与UDP传输的区别

UTP的特性

  • 面向连接的 可靠的 全双工的 流式传输
  • 面向连接 :同一时刻只能和一个客户端通信
  • 三次握手、四次挥手
  • 可靠的 :数据不丢失、慢
  • 全双工 :能够双向通信
  • 流式传输 :粘包 无边界

UDP的特性

  • 无连接的 面向数据包 不可靠的 快速的
  • 无连接的 :不需要accept/connect 也没有握手
  • 面向数据包的 :不会粘包
  • 不可靠的 :没有自动回复的机制
  • 快速的 :没有那些复杂的计算、保证数据传输的机制

我们从上面看到,tcp为什么会黏包的原因:本地端不知道发送端具体发送了多长的字符串,解决办法就是自定义协议,规定在传输之前先要传输的大小先行发送过去。在对方来接收规定长度的文件。

3.基于tcp的low版带验证功能的FTP小程序

做实验前谨记一个传大文件需要先传一个字典过去,让对方知道

3.1实验一

目的:服务器以及客户端互传文件并动态校验MD5

#服务端,比较low

import socket
import struct
import json
import hashlib
import os sk = socket.socket()#网络传输基本配置
sk.bind(('127.0.0.1',8500))#本地端口
sk.listen()
conn,addr = sk.accept() def download(file_dic):#客户端上传
print(3)
while True:
file_name = file_dic['file_name']#获取文件名
file_size = file_dic['file_size']#获取文件大小
ret = file_write(file_size,file_name)#收到的文件的MD5值
print(ret)
send_header(ret)#发送给客户端,服务器端的MD5值
print(addr,'接收成功!')
break def upload(file_dic):#客户端下载
while True:
isfile_dict = {}
file_name = file_dic['file_name']
if os.path.isfile(file_name):
isfile_dict['flag'] =1
send_header(isfile_dict)
send_file_dic ={}
send_file_dic['file_name'] = file_name
send_file_dic['file_size'] = os.path.getsize(file_name)
print(send_file_dic)
send_header(send_file_dic) #发送头文件
ret =file_read(file_name)#传输具体的文件获取MD5值
send_header(ret) # 发送给客户端,服务器端的MD5值
print(addr,'发送成功!')
break
else:
isfile_dict['flag'] = 0
send_header(isfile_dict)
break def get_header(date):#获取头文件
header_json = date.decode()
header_dic = json.loads(header_json)
return header_dic def send_header(obj):#发送头文件
header_json = json.dumps(obj) # 头文件的变为str类型
header_bytes = header_json.encode() # 头文件变为bytes类型
header_len = struct.pack('i', len(header_bytes)) # 计算头文件的长度
conn.send(header_len) # 发送头文件的长度
conn.send(header_bytes) # 发送头文件 def file_write(file_size,filename):#文件写入,同时得到写入后的文件的MD5值
recevive_num = 0
has = hashlib.md5()
with open(filename,'wb')as f2:
while recevive_num< file_size:
contact = conn.recv(1024)
if contact:
f2.write(contact)
recevive_num += len(contact)
has.update(contact)
else:
break
return {'MD5':has.hexdigest()} def file_read(filename):#文件读取,同时得到他的MD5值
has = hashlib.md5()
with open(filename,'rb')as f1:
while True:
contact = f1.read(1024)
conn.send(contact)
if contact:
has.update(contact)
else:
break
return {'MD5':has.hexdigest()} def run():
print(addr)
while True:
file_len = conn.recv(4)[0]
file_bytes = conn.recv(file_len)
file_dic =get_header(file_bytes)
print(file_dic)
if file_dic['operation']== 'download':
upload(file_dic)
elif file_dic['operation'] == 'upload':
download(file_dic) run()

#客户端

import socket
import struct
import json
import hashlib
import os
import sys header_dic ={}
menu=[
('上传文件',),
('下载文件',)
] def __upload():
while True:
file_get = input('请输入你要上传文件的绝对路径>>>').strip()
if os.path.isfile(file_get):
file_name = os.path.basename(file_get)#获取文件名
header_dic['file_name']=file_name
file_size = os.path.getsize(file_get)#获取文件大小
header_dic['file_size'] = file_size
header_dic['operation'] = 'upload'
send_header(header_dic)#发送文件的头文件
ret =file_read(file_get,file_size)#传输具体的文件获取MD5值
MD5_len= sk.recv(4)[0]
MD5_bytes = sk.recv(MD5_len)
MD5_dict = get_header(MD5_bytes)
if ret['MD5'] == MD5_dict['MD5']:
print('上传成功!')
break
else:
print('上传失败!')
break
else:
print('你输入的文件路径不存在,请重新确认!') def __download():
while True:
file_get = input('请输入你要下载的文件的文件名>>>').strip()
header_dic['file_name'] = file_get
header_dic['operation'] = 'download'
send_header(header_dic)#发送一个头文件给服务器
header_len = sk.recv(4)[0]#接收头文件的长度
header_bytes = sk.recv(header_len)#接收头文件的bytes类型
file_dic = get_header(header_bytes)#解包,获得头文件
if file_dic['flag'] == 0:
print('你要下载的文件不存在,请重新选择......')
else:
print('文件存在')
recv_file_header =sk.recv(4)[0]
recv_file_header_bytes = sk.recv(recv_file_header)
recv_file_dict = get_header(recv_file_header_bytes)
file_size = recv_file_dict['file_size']
file_name = recv_file_dict['file_name']
ret = file_write(file_size,file_name)
MD5_len = sk.recv(4)[0]#获得MD5字典的长度
MD5_bytes = sk.recv(MD5_len)
MD5_dict = get_header(MD5_bytes)#获取MD5字典的内容
if ret['MD5'] == MD5_dict['MD5']:
print('文件校验成功!')
break
else:
print('你接收的文件损坏,无法匹配!')
break def send_header(obj):#发送头文件
header_json = json.dumps(obj) # 头文件的变为str类型
header_bytes = header_json.encode() # 头文件变为bytes类型
header_len = struct.pack('i', len(header_bytes)) # 计算头文件的长度
sk.send(header_len) # 发送头文件的长度
sk.send(header_bytes) # 发送头文件 def get_header(date):#获取头文件
header_json = date.decode()
header_dic = json.loads(header_json)
return header_dic def file_read(filename,file_size):#文件读取,同时得到他的MD5值
has = hashlib.md5()
recevive_num = 0
with open(filename,'rb')as f1:
while True:
contact = f1.read(1024)
if contact:
sk.send(contact)
has.update(contact)
float_rate = int(recevive_num / file_size)
rate = round(float_rate * 100, 2)
sys.stdout.write('\r已下载:\033[1;32m{0}%\033[0m'.format(rate))
else:
break
return {'MD5':has.hexdigest()} def file_write(file_size,filename):#文件写入,同时得到写入后的文件的MD5值
recevive_num = 0
has = hashlib.md5()
with open(filename,'wb')as f2:
while recevive_num < file_size:
contact = sk.recv(1024)
if contact:
f2.write(contact)
recevive_num += len(contact)
has.update(contact)
float_rate = float(recevive_num / file_size)
rate = round(float_rate * 100, 2)
sys.stdout.write('\r已下载:\033[1;32m{}%\033[0m'.format(rate)) else:
break
print(2)
return {'MD5':has.hexdigest()} if __name__ == '__main__':
sk = socket.socket() # 网络传输基本配置
sk.connect(('127.0.0.1', 8500)) # 远端端口
while True:
for i,j in enumerate(menu,1):
print(i,j[0])
choice = int(input('请输入你想要实现的功能>>>').strip())
if choice == 1:
__upload()
elif choice == 2:
__download()

4.基于socketserver的多人聊天

#服务端
import socketserver class Myserver(socketserver.BaseRequestHandler):
def handle(self):
conn = self.request
while True:
date = conn.recv(1024).decode()
print(date)
msg = input('>>>').encode()
conn.send(msg) server = socketserver.ThreadingTCPServer(('127.0.0.1',8500),Myserver)
server.serve_forever()
#客户端
import socket sk = socket.socket()
sk.connect(('127.0.0.1',8500))
while True:
msg ='one' + input('>>>').strip()
sk.send(msg.encode())
data = sk.recv(1024).decode()
print(data) sk.close()

5.验证客户端的完整性

如果你想在分布式系统中实现一个简单的客户端链接认证功能,又不像SSL那么复杂,那么利用hmac+加盐的方式来实现

#服务端
import os
import hmac
import socket sk = socket.socket()
sk.bind(('127.0.0.1',8500))
sk.listen() def auth(conn):
secret_key = b'alexsb'
rand_b = os.urandom(32)
conn.send(rand_b)
obj = hmac.new(secret_key, rand_b)
res1 = obj.digest()
res2 = conn.recv(1024)
cmp_res = hmac.compare_digest(res1, res2)
return cmp_res conn,addr = sk.accept() res = auth(conn)
if res :
print('正常客户端')
conn.send(b'hello')
else:
conn.close()
conn.close()
sk.listen()
#客户端
import hmac
import socket sk = socket.socket()
sk.connect(('127.0.0.1',8500)) def auth(sk):
secret_key = b'alexsb'
rand_b =sk.recv(32)
obj = hmac.new(secret_key,rand_b)
res2 = obj.digest()
sk.send(res2) auth(sk)
msg = sk.recv(1024)
print(msg) sk.close()

6.socket的阻塞模型与非阻塞模型

只是涉及很浅显的一点阻塞模型

# 阻塞模型
# accept
# recv
# recvfrom # 非阻塞
# accept
# recv
# recvfrom import socket # sk = socket.socket()
# sk.setblocking(False)
# sk.bind(('127.0.0.1',9000))
# sk.listen()
# while True:
# try:
# sk.accept()
# except BlockingIOError:
# pass

day19-网络编程基础(二)的更多相关文章

  1. 第十章:Python の 网络编程基础(二)

    本課主題 Python中的作用域补充 socketserver 源码 线程的介绍和操作实战 进程的介绍和操作实战 协程的介绍和操作实战 本周作业 Python中的作用域补充 Python世界里沒有块级 ...

  2. iOS开发网络篇—网络编程基础

    iOS开发网络篇—网络编程基础 一.为什么要学习网络编程 1.简单说明 在移动互联网时代,移动应用的特征有: (1)几乎所有应用都需要用到网络,比如QQ.微博.网易新闻.优酷.百度地图 (2)只有通过 ...

  3. iOS开发网络篇—网络编程基础(一)

    一.为什么要学习网络编程 1.简单说明 在移动互联网时代,移动应用的特征有: (1)几乎所有应用都需要用到网络,比如QQ.微博.网易新闻.优酷.百度地图 (2)只有通过网络跟外界进行数据交互.数据更新 ...

  4. Java网络编程基础(Netty预备知识)

    今天在家休息,闲来无事,写篇博客,陶冶下情操~~~ =================我是分割线================ 最近在重新学习Java网络编程基础,以便后续进行Netty的学习. 整 ...

  5. 脑残式网络编程入门(二):我们在读写Socket时,究竟在读写什么?

    1.引言 本文接上篇<脑残式网络编程入门(一):跟着动画来学TCP三次握手和四次挥手>,继续脑残式的网络编程知识学习 ^_^. 套接字socket是大多数程序员都非常熟悉的概念,它是计算机 ...

  6. [转帖]脑残式网络编程入门(二):我们在读写Socket时,究竟在读写什么?

    脑残式网络编程入门(二):我们在读写Socket时,究竟在读写什么?     http://www.52im.net/thread-1732-1-1.html   1.引言 本文接上篇<脑残式网 ...

  7. python全栈开发从入门到放弃之socket网络编程基础

    网络编程基础 一 客户端/服务器架构 1.硬件C/S架构(打印机) 2.软件C/S架构 互联网中处处是C/S架构 如黄色网站是服务端,你的浏览器是客户端(B/S架构也是C/S架构的一种) 腾讯作为服务 ...

  8. 网络编程基础之C/S架构和TCP/IP协议

    一.何谓C/S架构 C指的是client(客户端软件),S指的是Server(服务端软件),既然我们的的标题是网络编程基础, 那我们就一起来学习怎样写一个C/S架构的软件,实现服务端与客户端软件基于网 ...

  9. 第5章 Linux网络编程基础

    第5章 Linux网络编程基础 5.1 socket地址与API 一.理解字节序 主机字节序一般为小端字节序.网络字节序一般为大端字节序.当格式化的数据在两台使用了不同字节序的主机之间直接传递时,接收 ...

  10. linux 网络编程 基础

    网络编程基础 套接字编程需要指定套接字地址作为参数,不同的协议族有不同的地址结构,比如以太网其结构为sockaddr_in. 通用套接字: struct sockaddr { sa_family_t ...

随机推荐

  1. 克拉克拉(KilaKila):大规模实时计算平台架构实战

    克拉克拉(KilaKila):大规模实时计算平台架构实战 一.产品背景:克拉克拉(KilaKila)是国内专注二次元.主打年轻用户的娱乐互动内容社区软件.KilaKila推出互动语音直播.短视频配音. ...

  2. [十]JavaIO之FilterInputStream FilterOutputStream

    FilterInputStream  FilterOutputStream都是装饰器模式中的Decorator抽象装饰角色 他们继承了各自的抽象构建InputStream 和OutputStream ...

  3. #1 爬虫:豆瓣图书TOP250 「requests、BeautifulSoup」

    一.项目背景 随着时代的发展,国人对于阅读的需求也是日益增长,既然要阅读,就要读好书,什么是好书呢?本项目选择以豆瓣图书网站为对象,统计其排行榜的前250本书籍. 二.项目介绍 本项目使用Python ...

  4. mac用pecl安装swoole可能出现的报错及解决办法

    一.用pecl安装swoole 2018年4月,由于homebrew的变动,导致无法使用brew install的方式安装php的扩展,现在改为用pecl安装,pecl安装swoole的方法为: pe ...

  5. 杭电ACM2013--蟠桃记

    蟠桃记 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submiss ...

  6. 从零开始学安全(三十七)●VM汇编环境搭建

    需要下载 vm 虚拟机 破解版连接 链接:https://pan.baidu.com/s/1r9MyPkNBmiYhQ8bdUxPmvQ 提取码:2o98 镜像文件和开发环境 链接:https://p ...

  7. 读书笔记之第五回深入浅出关键字---把new说透

    第五回深入浅出关键字---把new说透  ------你必须知道的.net读书笔记 new一个class时,new完成了以下两个方面的内容:一是调用newobj命令来为实例在托管堆中分配内存:二是调用 ...

  8. [PHP]MySQL的wait_timeout与pdo对象

    1.查看和设置mysql的wait_timeout的值 SHOW GLOBAL VARIABLES LIKE '%timeout%'; 设置wait_timeout的值 SET GLOBAL wait ...

  9. ueditor笔记

    一.ueditor是什么 UEditor 是由百度「FEX前端研发团队」开发的所见即所得富文本web编辑器,具有轻量,可定制,注重用户体验等特点,开源基于MIT协议,允许自由使用和修改代码. 二.ue ...

  10. 多线程(4)Task

    使用线程池使得创建线程已经很简单了,但是使用线程池不支持线程的取消,完成和失败通知等交互操作,为了解决这些问题,.net 4.0带来了TPL(Task Parallel Library)任务并行库,下 ...