使用网络TCP搭建一个简单文件下载器

说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家!

目录

一丶项目介绍

二丶服务器Server

三丶测试TCP server服务器

四丶客户端Client

五丶测试客户端向服务器下载文件


一丶项目介绍

1.叙述

生活中大家都使用过迅雷吧,用户在客户端上使用迅雷从服务器上download一个文件到客户端,今天博主就是使用TCP网络搭建一个客户端client连接服务器server,从服务器server上下载所想要下载的文件到客户端client上

2.项目环境

操作系统:Windows7 

IDE:PyCharm2017

编程语言:python3.x

测试工具:网络调试工具3.x

二丶服务器Server

1.在PyCharm中创建file_download_tcpServer.py和file_download_tcpClient.py文件用于实现tcp服务器客户端

2.首先在file_download_tcpServer.py中进行代码逻辑编写

  • step1 创建tcp socket套接字
tcp_server_socket = socket(AF_INET, SOCK_STREAM)
  • step2 绑定本地IP和端口
tcp_server_socket.bind(('', 8888))
  • step3 使用listen将主动套接字变为被动套接字
tcp_server_socket.listen(128)
  • step4 等待客户端的链接,即为这个客户端发送文件,因为不止一个客户连接,此时需要将(step4~7)代码写在while True里面
client_socket, clientAddr = tcp_server_socket.accept()
  • step5 显示连接的客户端用户信息
print("用户%s 已连接"% str(clientAddr))
  • step6 接收客户端发送过来的数据获取客户要下载的文件,并打印显示
recv_data = client_socket.recv(1024)  # 接收1024个字节
file_name = recv_data.decode("utf-8")
print("对方请求下载的文件名为:%s" % file_name)
  • step7 根据客户请求下载的文件名,获取该文件内容,并发送给客户端
try:with open(filename, "rb") as f:file_content = f.read()
except Exception as e:print("获取文件内容出错:", e)if file_content:client_socket.send(file_content)
# 关闭该套接字
client_socket.close()
  • step8 关闭服务器监听套接字
tcp_server_socket.close()

3.封装(解耦)代码,博主之所以这样做,是为了让大家了解一个正确开发过程,提高代码复用性

从上面代码可以看出耦合性比较严重,看着杂乱无章比较费劲,所以需要对代码进行解耦操作,降低代码耦合性,获取客户端下载文件内容可以封装到一个方法里(get_file_content),而tcp 服务器创建套接字以及关闭都可以封装到main方法里面,如下所示

def get_file_content(filename):"""获取文件内容"""try:with open(filename, "rb") as f:content = f.read()return contentexcept Exception as e:print("获取文件内容出错:", e)def main():# 创建sockettcp_server_socket = socket(AF_INET, SOCK_STREAM)# 绑定本地信息tcp_server_socket.bind(('', 8888))# 使用listen将主动套接字变为被动套接字tcp_server_socket.listen(128)while True:# 等待客户端的链接,即为这个客户端发送文件client_socket, clientAddr = tcp_server_socket.accept()print("用户%s 已连接"% str(clientAddr))# 接收客户端发送过来的数据获取客户要下载的文件名recv_data = client_socket.recv(1024)  # 接收1024个字节file_name = recv_data.decode("utf-8")print("对方请求下载的文件名为:%s" % file_name)file_content = get_file_content(file_name)# 发送文件的数据给客户端,获取文件内容使用rb二进制,所以这里不需要进行encode编码操作if file_content:client_socket.send(file_content)# 关闭客户端套接字client_socket.close()# 关闭服务器监听套接字tcp_server_socket.close()if __name__ == "__main__":main()

4. 指定服务器运行方式为python3 xxx.py 8888,将服务器绑定端口号传入到代码中

  • step1 指定TCP服务器启动为终端命令python3 xxx.py 8888方式,这个比较新颖,这里博主给大家详细进行演示,这里博主在项目目录下创建demo.py文件用于演示,在demo.py中进行如下编写
import sys
print(len(sys.argv))
  • step2 在pycharm中直接运行run demo.py结果如下

  • step3 在pycharm Terminal终端执行python3 demo.py 8888 ,打印出sys.argv的长度为2,结果为列表所以打印的第一个元素值为文件名第二元素的值为传入的端口号,所以说如果sys.argv的长度为1代表直接运行,为2时表示是以python3 xxx.py 8888方式运行,由此可以进行逻辑判断

 

  • step4 在main主函数第一行加入以下代码,并将bing方法中的端口参数修改为port
def main():import sysif len(sys.argv) != 2:print("请按照如下方式运行:python3 xxx.py 8888")returnelse:# 运行方式为python3 xxx.py 8888port = int(sys.argv[1]) # 8888

 三丶测试TCP server服务器

1.在Terminal终端执行python3 file_download_tcpServer.py 没有传入端口号,出现定义的提示

2.在Terminal终端执行python3 file_download_tcpServer.py 8888即成功运行tcp 服务器并绑定8888端口,终端光标开始闪烁等待客户端的连接

3.打开网络调试助手,选择TCP client客户端,IP地址为本机IP 端口为服务器绑定端口号8888,

4.点击连接成功后,回到pycharm Terminal终端,此时终端显示用户XXXX已连接

5.在网络调试助手中发送demo.py文件名(client发送下载文件名必须存在于服务器端),此时服务器获取客户端发送的下载文件名,获取该文件的内容发送给客户端,代表服务器代码逻辑编写正确

  • step1 服务端显示如下

  • step2 客户端显示如下 

 四丶客户端Client

1.在file_download_tcpClient.py中进行代码逻辑编写,相对服务器来说客户端的代码实现就比较简单,首先定义main主函数用于客户端创建套接字连接目标服务器

  • step1 创建套接字
tcp_client_socket = socket(AF_INET, SOCK_STREAM)
  • step2 连接目标服务器
tcp_client_socket.connect((input("请输入服务器ip:"), int(input("请输入服务器port:"))))
  • step3 输入要下载的文件名,并向服务器发送
file_name = input("请输入要下载的文件名:")
tcp_client_socket.send(file_name.encode("utf-8"))
  • step4 接收服务器发送过来的数据,接收1024个字节(1K)
recv_data = tcp_client_socket.recv(1024)
  • step5 接收数据不为空时,写入到本地客户端
if recv_data:with open("[接收]"+file_name, "wb") as f:f.write(recv_data)
  • step6 关闭客户端套接字
tcp_client_socket.close()

2.客户端完整代码

from socket import *def main():# 创建socket套接字tcp_client_socket = socket(AF_INET, SOCK_STREAM)# 连接目标服务器tcp_client_socket.connect((input("请输入服务器ip:"), int(input("请输入服务器port:"))))# 输入需要下载的文件名file_name = input("请输入要下载的文件名:")# 向服务器发送文件下载请求tcp_client_socket.send(file_name.encode("utf-8"))# 接收服务器发送过来的数据recv_data = tcp_client_socket.recv(1024)print('接收到的数据为:', recv_data.decode('utf-8'))# 接收数据不为空时,写入到本地客户端,if recv_data:with open("[接收]"+file_name, "wb") as f:f.write(recv_data)# 关闭套接字tcp_client_socket.close()if __name__ == "__main__":main()

五丶测试客户端向服务器下载文件

1.首先在Terminal终端上执行python3 file_download_tcpServer.py 8888将服务器运行在8888端口上,此时服务器正等待客户端连接

2.在pycharm上直接run运行 file_download_tcpClient.py客户端

  • step1 运行后则显示输入服务器的IP,端口以及要下载的文件名,发送请求给服务器成功则服务器会将该文件的内容发送给客户端,此时打印出demo.py文件中的内容,并在本地客户端成功创建一个[接收]demo.py文件

  • step2 查看是否存在 [接收]demo.py文件

  • step3 查看该文件内容,与demo.py内容一致表示从服务器下载文件成功

  • step4 查看Terminal服务器显示,显示出客户端请求下载的文件名正确

3.在服务器目录下存放一张1.jpg头像图片,进行测试

  • step1 查看1.jpg文件

  • step2 因为该图片大小为42.04K所在在客户端中recv方法的参数值必须大于文件大小值,所以这里我修改为100000,1024=1k,不然的话下载的图片会出现模糊以及残缺
recv_data = tcp_client_socket.recv(100000)
  • step3 运行file_download_tcpClient.py程序,向服务器发送下载1.jpg文件请求,

  • step4  查看下载后的[接收]1.jpg文件并与1.jpg文件进行对比,属性均一致,表示搭建的tcp文件下载器成功

 

 

转载于:https://www.cnblogs.com/cdtaogang/p/10631071.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/569756.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

动态规划在求解背包问题中的应用(JAVA)--回溯法、记忆化法

动态规划在求解背包问题中的应用 背包问题向来是动态规划的典型问题,给定n个重量为w1,w2,...,wn,价值为v1,v2,...,vn的物品和一个称重量为W的背包,求这些物品中最优价值的一个子集,且能够装到背包中。 之前用蛮力法做过背包问题蛮…

JS跨域问题

因为浏览器的同源策略,默认情况下,JavaScript在发送AJAX请求时,URL的域名必须和当前页面完全一致。 完全一致的意思是,域名要相同(www.example.com和example.com不同),协议要相同(ht…

svn 服务器的搭建以及客户端的使用

1、svn 服务器的搭建以及客户端的使用,安装见下面的博客 https://blog.csdn.net/zh123456zh789/article/details/80921179 说明:服务器只是用来存储数据,服务器上的数据可以通过客户端torisesvn进行操作。比如将自己的项目存到服务器&#xf…

动态规划在求解传递闭包问题中的应用(JAVA)--Warshell算法

动态规划在求解传递闭包问题中的应用: 传递闭包:对于n个顶点有向图来说,如果第i个顶点到第j个顶点之间存在一条有效的有向路径(即长度大于0的路径),那么T(i, j) 1,否则T(i, j) 0。例如:求解传…

Centos 7 LVM xfs文件系统修复

情况1: [sda] Assuming drive cache: write through Internal error xfs XFS_WANT_CORRUPTED_GOTO at line 1662 of file fs/xfs/libxfs/xfs_alloc.c Caller xfs_free_extent0x130 [xfs] Internal error xfs_trans_cancel at line 990 of file fs/xfs/xfs_trans.c.C…

动态规划在求解全源最短路径中的应用(JAVA)--Floyd算法

参考图论算法(二)-最短路径的Dijkstra [ 单源 ] 和Floyd[ 多源 ] 解法(JAVA )这种算法也叫Floyd-Warshell算法,虽然和Warshell算法名字相近,算法思想也相近,但确实是两种算法。对于一个带权图&a…

录播图的分页使用进度条形式显示

本次我是使用的slick轮播图插件,其官网网址如下: http://kenwheeler.github.io/slick/,下面是轮播图中的代码,如果你不知道效果是什么样子,亦可以去看一下阿里云的官网:https://www.aliyun.com/?utm_conte…

贪婪算法在求解最小生成树中的应用(JAVA)--Prim算法

贪婪算法:通过一系列步骤来构造问题的解,每一步对目前构造的部分分解做一个拓展,直到获得问题的完整解为止,而算法的核心思想就在于,算法的每一步都必须满足以下条件:可行(满足问题的约束条件)、…

贪婪算法在求解最小生成树中的应用(JAVA)--Kruskal算法

Kruskal算法又被称为“加边法”,这种算法会将加权连通图的最小生成树看成具有V-1条边的无环子图,且边的权重和最小。算法开始时,会按照权重的非递减顺序对图中的边排序,之后迭代的以贪婪的方式添加边。 下面以下图为例来讲解Krusk…

贪婪算法在求解最短路径中的应用(JAVA)--Dijkstra算法

最短路径问题最经典的算法就是Dijkstra算法,虽然不如Floyd算法能够求全源的最短路径,但是在效率上明显强于Floyd算法。 想了解Floyd算法的读者可以参考动态规划在求解全源最短路径中的应用(JAVA)--Floyd算法 单源最短路径问题是对…

贪婪算法在解决哈夫曼树及编码问题中的应用

哈夫曼编码,是一种可变字长编码(VLC)的高效算法。该算法是Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码。 相比定长编码来说,这种编码实现的压缩率&#xff…

素数筛法求十亿内所有质数的和(C++)

埃拉托斯特尼筛法&#xff08;又称埃氏筛&#xff09;的基本思想是&#xff1a;要得到自然数n以内的全部素数&#xff0c;必须把不大于的所有素数的倍数剔除&#xff0c;剩下的就是素数。 时间复杂度O(nloglogn) #include <iostream> #include <math.h> using na…

spring事务的传播机制新解

以下是事物的传播机制&#xff1a; Transactional(propagationPropagation.REQUIRED)如果有事务, 那么加入事务, 没有的话新建一个(默认情况下)Transactional(propagationPropagation.NOT_SUPPORTED)容器不为这个方法开启事务Transactional(propagationPropagation.REQUIRES_NE…

时空权衡在模式匹配算法中的应用(JAVA)--Horspool算法(简化版BM算法)

模式匹配是数据结构中字符串的一种基本运算&#xff0c;给定一个子串&#xff0c;要求在某个字符串中找出与该子串相同的所有子串。假设P是给定的子串&#xff0c;T是待查找的字符串&#xff0c;要求从T中找出与P相同的所有子串&#xff0c;这个问题成为模式匹配问题。P称为模式…

从wireshake分析http和https的通信过程

参考文章: Wireshark基本介绍和学习TCP三次握手【技术流】Wireshark对HTTPS数据的解密Wireshark/HTTPSJourney to HTTP/2以TCP/IP协议为例&#xff0c;如何通过wireshark抓包分析&#xff1f;TCP三次握手和四次挥手Https详解wireshark抓包演示前言 面试被问到有没有用过抓包工具…

Java对象的序列化和反序列化

原文&#xff1a;https://www.cnblogs.com/xdp-gacl/p/3777987.html 一、序列化和反序列化的概念 把对象转换为字节序列的过程称为对象的序列化。  把字节序列恢复为对象的过程称为对象的反序列化。 对象的序列化主要有两种用途&#xff1a; 1&#xff09; 把对象的字节序列永…

安装oracle 11g时,报启动服务出现错误,找不到OracleMTSRecoveryService的解决方法

1、打开注册表看看&#xff1a;HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services下&#xff0c;找到OracleMTSRecoveryService及OracleRemExecService&#xff0c;查看ImagePath对应路径。 2、修改ImagePath路径为xxxxxxx\dbhome_1\bin\xxxxxxxxx即可【修改为你本地真实路…

django系列5.1--ORM对数据库的操作

Django--—ORM数据库操作(图书管理系统基本实例) 一.基本知识 MVC模式&#xff08;Model–view–controller&#xff09;是软件工程中的一种软件架构模式&#xff0c;把软件系统分为三个基本部分&#xff1a;模型&#xff08;Model&#xff09;、视图&#xff08;View&#xff…

蓝桥杯第七届决赛JAVA真题----路径之谜

路径之谜小明冒充X星球的骑士&#xff0c;进入了一个奇怪的城堡。 城堡里边什么都没有&#xff0c;只有方形石头铺成的地面。 假设城堡地面是 n x n 个方格。【如图1.png】所示。按习俗&#xff0c;骑士要从西北角走到东南角。 可以横向或纵向移动&#xff0c;但不能斜着走&…

蓝桥杯第七届决赛JAVA真题----广场舞

广场舞LQ市的市民广场是一个多边形&#xff0c;广场上铺满了大理石的地板砖。 地板砖铺得方方正正&#xff0c;就像坐标轴纸一样。 以某四块砖相接的点为原点&#xff0c;地板砖的两条边为两个正方向&#xff0c;一块砖的边长为横纵坐标的单位长度&#xff0c;则所有横纵坐标都…