博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python Day32
阅读量:6976 次
发布时间:2019-06-27

本文共 4411 字,大约阅读时间需要 14 分钟。

半链接数:

三次握手没有完成,称为半链接

原因:1.客户端恶意没有接收服务器返回的消息,没有返回第三次握手消息。这样如果大量的客户端这么做就是洪水攻击。2.服务器没空及时处理客户端的请求

socket中listen(半链接最大数量)

粘包问题:

TCP流式协议, 数据之间没有分界, 就像水 一杯水和一杯牛奶倒在一起了!

UDP 用户数据报协议

粘包 仅发生在TCP协议中

  1. 发送端 发送的数据量小 并且间隔短 会粘

  2. 接收端 一次性读取了两次数据的内容 会粘

  3. 接收端 没有接收完整 剩余的内容 和下次发送的粘在一起

无论是那种情况,其根本原因在于 接收端不知道数据到底有多少

解决方案就是 提前告知接收方 数据的长度

解决方案:

先发长度给对方,再发真实数据

发送端

1.使用struct 将真实数据的长度转为固定的字节数据

2.发送长度数据

3.发送真实数据

接收端

1.先收长度数据 字节数固定

2.再收真实数据 真实可能很长 需要循环接收

发送端和接收端必须都处理粘包 才算真正的解决了

 

#    ==================================================客户端import socketfrom 二_CMD程序 import smallToolimport structclient = socket.socket()try:    client.connect(("127.0.0.1",1688))    print("链接成功!")    while True:        msg = input("请输入要执行指令:").strip()        if msg == "q": break        if not msg: continue        # 发送指令        # 先发长度        len_bytes = struct.pack("q",len(msg.encode("utf-8")))        client.send(len_bytes)        # 在发指令        client.send(msg.encode("utf-8"))        data = smallTool.recv_data(client)        print(data.decode("GBK"))    client.close()except ConnectionRefusedError as e:    print("链接服务器失败了!",e)except ConnectionResetError as e:    print("服务器挂了!", e)    client.close()import socketimport subprocessimport structfrom 二_CMD程序 import  smallToolserver = socket.socket(socket.AF_INET,socket.SOCK_STREAM)server.bind(("127.0.0.1",1688))server.listen()# backwhile True:    # socket,addr一个元组 客户端的ip和port    client,addr = server.accept()    print("客户端链接成功!")    # 循环收发数据    while True:        try:            cmd = smallTool.recv_data(client)            if not cmd:                break            print(cmd)            p = subprocess.Popen(cmd.decode("utf-8"),shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)            # 不要先读err错误信息  它会卡主  原因不详  linux不会有问题  tasklist  netstat - ano啥的            data = p.stdout.read()            err_data = p.stderr.read()            len_size = len(data) + len(err_data)            print("服务器返回了: %s " %  len_size)            len_bytes = struct.pack("q",len_size)            # 在发送真实数据前先发送 长度            client.send(len_bytes)            # 返回的结果刚好就是二进制            # 发送真实数据            client.send(data + err_data)        except ConnectionResetError as e:            print("客户端了挂了!",e)            break    client.close()#server.close()

自定义报头:

当需要在传输数据时 传呼一些额外参数时就需要自定义报头

报头本质是一个json 数据

具体过程如下:

发送端

1 发送报头长度

2 发送报头数据 其中包含了文件长度 和其他任意的额外信息

3 发送文件内容

 

接收端

1.接收报头长度

2.接收报头信息

3.接收文件内容

import socketimport osimport structimport json"""客户端接链成功我就给你发个文件过去  固定的文件下载"""server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)server.bind(("127.0.0.1",1688))server.listen()# backwhile True:    # socket,addr一个元组 客户端的ip和port    client,addr = server.accept()    print("客户端链接成功!")    f = None    try:        path = r"F:\2.半链接数.mp4"        file_size = os.path.getsize(path)        # 我想把文件名发过去        file_info = {
"file_name":"半链接数.mp4","file_size":file_size,"md5":"xxxxxxxxx"} json_str = json.dumps(file_info).encode("utf-8") # 发送报头长度 client.send(struct.pack("q",len(json_str))) # 发报头 client.send(json_str) # 发文件了 # 发送文件数据 f = open(path,"rb") # 循环发送文件内容 每次发2048 while True: temp = f.read(2048) if not temp: break client.send(temp) print("文件发送完毕!") except Exception as e: print("出问题了",e) finally: if f:f.close() client.close() # 无论是否抛出异常 文件都要关闭#server.close()# 用户可以指定要下载什么文件 FTP"""客户端输入指令服务器接收指令并执行 最后返回执行结果"""import socketimport structimport jsonclient = socket.socket()try: client.connect(("127.0.0.1",1688)) print("链接成功!") # 1.先收报头长度 head_size = struct.unpack("q",client.recv(8))[0] # 2.收报头数据 head_str = client.recv(head_size).decode("utf-8") file_info = json.loads(head_str) print("报头数据:",file_info) file_size = file_info.get("file_size") file_name = file_info.get("file_name") # 3.再收文件内容 # 已接收大小 recv_size = 0 buffer_size = 2048 f = open(file_name,"wb") while True: if file_size - recv_size >= buffer_size: temp = client.recv(buffer_size) else: temp = client.recv(file_size - recv_size) f.write(temp) recv_size += len(temp) print("已下载:%s%%" % (recv_size / file_size * 100)) if recv_size == file_size: break f.close()except ConnectionRefusedError as e: print("链接服务器失败了!",e)

 

转载于:https://www.cnblogs.com/xinfan1/p/10949551.html

你可能感兴趣的文章
AD走圆弧走线
查看>>
PHP获取Linux当前目录下文件并实现下载功能
查看>>
python-操作hive
查看>>
(Spring4 json入门)Spring4+SpringMVC+页面数据发送与接收(json格式)
查看>>
852. Peak Index in a Mountain Array
查看>>
Vijos P1114 FBI树【DFS模拟,二叉树入门】
查看>>
Web版简易五子棋
查看>>
set集合
查看>>
sersync实时同步
查看>>
修改Http消息的消息头Host
查看>>
获取ActionBar高度
查看>>
.NET面试题解析(06)-GC与内存管理
查看>>
[Android学习笔记]Context简单理解
查看>>
为确保固定资产的财务帐与实物帐一致,应采取的措施
查看>>
Codeforces Round #224 (Div. 2)
查看>>
linux基础—课堂随笔05_文本三剑客之SED
查看>>
MVC 数据验证
查看>>
TCP协议发送/接收数据
查看>>
python 3.5 连接mysql数据库
查看>>
输入和输出
查看>>