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

目录

一丶项目介绍

二丶服务器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 content
    except Exception as e:
        print("获取文件内容出错:", e)

def main():
    # 创建socket
    tcp_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 sys
    if len(sys.argv) != 2:
        print("请按照如下方式运行:python3 xxx.py 8888")
        return
    else:
        # 运行方式为python3 xxx.py 8888
        port = 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文件下载器成功

最新文章

  1. MVC视图请求流程视图
  2. struts2数据校验与国际化
  3. angular依赖注入的理解(转)
  4. The plot Function in matlab
  5. 临时禁用Resharper
  6. lucene索引并搜索mysql数据库[转]
  7. 测试横竖屏切换时activity 的生命周期
  8. 获取编译学习笔记 (六)—— si、di,双环
  9. CDOJ 1271 Search gold
  10. Fabric 1.0的多机部署
  11. 了解git的命令行使用
  12. eclipse的常用设置(空间新建后需要的配置)
  13. Android网络通信(7):NFC
  14. 入坑Vue
  15. Python的文件读写
  16. mysql 存储过程用程序调的问题
  17. [转载]C#深拷贝的方法
  18. 2018/3/20 noip模拟赛 5分
  19. Mysql插入数据报错java.sql.SQLException: Incorrect string value: '\xF0\x9F\x93\x8D\xE6\x88...'
  20. node.js 连接 mysql

热门文章

  1. 基于Linux的智能家居的设计(2)
  2. 五大最受欢迎的BUG管理系统
  3. Android的矩阵(一):ColorMatrix
  4. 外部数据库驱动程序XX中的意外错误
  5. BZOJ3569: DZY Loves Chinese II(线性基构造)
  6. Hexo 相册实践
  7. JAVA文件读取FileReader
  8. JAVA数组的基本方法
  9. 洛谷 P3692 [PUB1]夏幻的考试
  10. 可靠的UDP连接 & MTU MSS