python实现简单tftp(基于udp协议)


Posted in Python onJuly 30, 2018

本文实例为大家分享了python实现简单tftp的具体代码,供大家参考,具体内容如下

python实现简单tftp(基于udp协议)

  • tftp是基于udp的协议
  • 实现简单的tftp,首先要有tftp的协议图。
  • tftp默认接收端口为69,但每次有连接过来后,tftp会随机分配一个端口来专门为这个连接来服务。
  • 操作码:1.上传 2.下载 3.传数据 4.接收确认 5.错误码

tftp服务器简单实现:

from threading import Thread
from socket import *
import struct

def upload(filename,user_ip,user_port):
 num = 0
 f = open(filename,'ab') 
 s_up = socket(AF_INET,SOCK_DGRAM)
 send_data_1 = struct.pack("!HH",4,num)
 s_up.sendto(send_data_1,(user_ip,user_port)) #第一次用随机端口发送

 while True:
  recv_data,user_info = s_up.recvfrom(1024) #第二次客户连接我随机端口
  caozuohao_up,ack_num = struct.unpack('!HH',recv_data[:4])
  print(caozuohao_up,ack_num,num)
  if int(caozuohao_up) == 3 and ack_num == num :
   f.write(recv_data[4:])
   send_data = struct.pack("!HH",4,num)
   s_up.sendto(send_data,(user_ip,user_port)) #第二次我用随机端口发
   num = num + 1
   if len(recv_data) < 516:
    print(user_ip+'上传文件'+filename+':完成')
    f.close()
    exit()
  
def download(filename,user_ip,user_port):
 s_down = socket(AF_INET, SOCK_DGRAM)
 num = 0

 try:
  f = open(filename,'rb')
 except:
  error_data = struct.pack('!HHHb',5,5,5,num)
  s_down.sendto(error_data, (user_ip,user_port)) #文件不存在时发送
  exit() #只会退出此线程

 while True:
  read_data = f.read(512)
  send_data = struct.pack('!HH',3,num) + read_data
  s_down.sendto(send_data, (user_ip,user_port)) #数据第一次发送
  if len(read_data) < 512:
   print('传输完成, 对方下载成功')
   exit()  
  recv_ack = s_down.recv(1024) #第二次接收
  caozuoma,ack_num = struct.unpack("!HH", recv_ack)
#  print(caozuoma,ack_num,len(read_data))
  num += 1
  if int(caozuoma) != 4 or int(ack_num) != num-1 :
   exit()
 f.close()

s = socket(AF_INET,SOCK_DGRAM)
s.bind(('',69))

def main():
 while 1:
  recv_data,(user_ip,user_port) = s.recvfrom(1024) #第一次客户连接69端口
  print(recv_data, user_ip, user_port)
  if struct.unpack('!b5sb',recv_data[-7:]) == (0, b'octet', 0):
   caozuoma = struct.unpack('!H',recv_data[:2])
   filename = recv_data[2:-7].decode('gb2312')
   if caozuoma[0] == 1:
    print('对方想下载数据',filename)
    t = Thread(target = download, args = (filename,user_ip,user_port)) 
    t.start()   
   elif caozuoma[0] == 2:
    print('对方想上传数据',filename)
    t = Thread(target = upload, args = (filename,user_ip,user_port)) 
    t.start()   

if __name__ == '__main__':
 main()

上传数据简单实现:

#!/usr/bin/env python3
#coding=utf-8

import struct
from socket import *


server_ip = '192.168.119.157'
send_data_1 = struct.pack('!H8sb5sb',2,'王辉.jpg'.encode('gb2312'),0,b'octet',0)
s = socket(AF_INET,SOCK_DGRAM)
s.sendto(send_data_1,(server_ip,69)) #第一次发给服务器69端口

f = open('王辉.jpg','rb')

recv_data = s.recvfrom(1024) #第一次接收数据
rand_port = recv_data[1][1]
print()
ack_num = struct.unpack("!HH",recv_data[0][:4])
num = 0
while True:
 read_data = f.read(512)
 send_data = struct.pack('!HH',3,num) + read_data
 s.sendto(send_data,(server_ip,rand_port)) #第二次发给服务器的随机端口
 recv_data_2,userinfo = s.recvfrom(1024)
 print(recv_data_2)
 ack_num = struct.unpack('!H',recv_data_2[2:4])
 print(len(read_data),num,ack_num[0],rand_port)
 if len(read_data) < 512 or ack_num[0] != num :
  break
 num = num + 1

下载数据简单实现:

#!/usr/bin/env python3
#coding=utf-8

import struct
from socket import *

filename = 'test.jpg'
server_ip = '192.168.1.113'

send_data = struct.pack('!H%dsb5sb'%len(filename),1,filename.encode('gb2312'),0,'octet'.encode('gb2312'),0)
s = socket(AF_INET,SOCK_DGRAM)
s.sendto(send_data,(server_ip,69)) #第一次发送, 连接服务器69端口

f = open(filename,'ab')

while 1:
 recv_data = s.recvfrom(1024) #接收数据
 caozuoma,ack_num = struct.unpack('!HH',recv_data[0][:4]) #获取数据块编号
 rand_port = recv_data[1][1] #获取服务器的随机端口

 if int(caozuoma) == 5:
  print('服务器返回: 文件不存在...')
  break
 print(caozuoma,ack_num,rand_port,len(recv_data[0]))

 f.write(recv_data[0][4:])
 if len(recv_data[0]) < 516:
  break
 
 ack_data = struct.pack("!HH",4,ack_num)
 s.sendto(ack_data,(server_ip,rand_port)) #回复ACK确认包

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python多线程编程(六):可重入锁RLock
Apr 05 Python
Python类属性与实例属性用法分析
May 09 Python
python使用win32com库播放mp3文件的方法
May 30 Python
python实现红包裂变算法
Feb 16 Python
Python中的数学运算操作符使用进阶
Jun 20 Python
特征脸(Eigenface)理论基础之PCA主成分分析法
Mar 13 Python
Python实现爬虫从网络上下载文档的实例代码
Jun 13 Python
python导入不同目录下的自定义模块过程解析
Nov 18 Python
Python中logging日志库实例详解
Feb 19 Python
Python编程快速上手——Excel到CSV的转换程序案例分析
Feb 28 Python
Django-xadmin后台导入json数据及后台显示信息图标和主题更改方式
Mar 11 Python
python 实现两个线程交替执行
May 02 Python
Python实现处理逆波兰表达式示例
Jul 30 #Python
python实现自动网页截图并裁剪图片
Jul 30 #Python
python中redis查看剩余过期时间及用正则通配符批量删除key的方法
Jul 30 #Python
对PyTorch torch.stack的实例讲解
Jul 30 #Python
Python 中字符串拼接的多种方法
Jul 30 #Python
TensorFlow Session会话控制&amp;Variable变量详解
Jul 30 #Python
TensorFlow Session使用的两种方法小结
Jul 30 #Python
You might like
phpMyAdmin出现无法载入 mcrypt 扩展,请检查PHP配置的解决方法
2012/03/26 PHP
php cURL和Rolling cURL并发方式比较
2013/10/30 PHP
php+mysqli使用面向对象方式查询数据库实例
2015/01/29 PHP
php 一维数组的循环遍历实现代码
2017/04/10 PHP
js几个不错的函数 $$()
2006/10/09 Javascript
Jquery 基础学习笔记之文档处理
2009/05/29 Javascript
js下将字符串当函数执行的方法
2011/07/13 Javascript
js字符编码函数区别分析
2011/12/28 Javascript
javascript实现简易计算器的代码
2016/05/31 Javascript
高效的jQuery代码编写技巧总结
2017/02/22 Javascript
详解ESLint在Vue中的使用小结
2018/10/15 Javascript
ES6入门教程之Array.from()方法
2019/03/23 Javascript
nodejs 递归拷贝、读取目录下所有文件和目录
2019/07/18 NodeJs
vue实现公告栏文字上下滚动效果的示例代码
2020/06/16 Javascript
了不起的11个JavaScript代码重构最佳实践小结
2021/01/11 Javascript
[02:56]DOTA2英雄基础教程 巨魔战将
2013/12/10 DOTA
Python实现Linux的find命令实例分享
2017/06/04 Python
名片管理系统python版
2018/01/11 Python
python实现用户答题功能
2018/01/17 Python
django 发送手机验证码的示例代码
2018/04/25 Python
python主线程捕获子线程的方法
2018/06/17 Python
python输出100以内的质数与合数实例代码
2018/07/08 Python
Python3.5 win10环境下导入kera/tensorflow报错的解决方法
2019/12/19 Python
python读取ini配置的类封装代码实例
2020/01/08 Python
使用celery和Django处理异步任务的流程分析
2020/02/19 Python
Python二元算术运算常用方法解析
2020/09/15 Python
使用Python webdriver图书馆抢座自动预约的正确方法
2021/03/04 Python
无畏的旅行:Intrepid Travel
2017/12/20 全球购物
Spartoo荷兰:鞋子、包包和服装
2018/07/12 全球购物
实习护理工作自我评价
2013/09/25 职场文书
产品工艺师的岗位职责
2013/11/15 职场文书
《草虫的村落》教学反思
2014/02/16 职场文书
和谐社区口号
2014/06/19 职场文书
2015年评职称工作总结范文
2015/04/20 职场文书
2015年数学教研工作总结
2015/07/22 职场文书