码迷,mamicode.com
首页 > 编程语言 > 详细

python基础--socket套接字、粘包问题

时间:2019-08-08 00:27:57      阅读:139      评论:0      收藏:0      [点我收藏+]

标签:port   class   注意   lse   NPU   python基础   col   字符串   ack   

本地回环地址:127.0.0.1

简易版服务端:

import socket
?
server = socket.socket()  # 就比如买了一个手机
server.bind(("127.0.0.1",8080))  # bind中绑定的是IP地址和端口号,注意是一个元组,就比如,将手机卡,插入了手机
server.listen(5)  # 半连接池,最大等待连接数为5个,就比如开机
conn,address = server.accept()  # 接听电话等着别人给你打电话
?
date = conn.recv(1024)  # 听别人说话,接收1023个字节数
print(date)
conn.send(b"hello")  # 给别人回话
?
?
conn.close()  # 挂断电话
server.close()  # 关机

 

简易版客户端:

import socket
?
client = socket.socket()  #拿电话
client.connect(("127.0.0.1",8080))  #绑定的是IP地址和端口号,也是一个元组 拨号
?
client.send(b"hello")  # 对别人发消息
?
date = client.recv(1024)  #接收别人说话,没次接收1024个字节
print(date)
?
client.close()  # 挂电话

 

 

 

注意:在写服务端和客户端的时候send和recv需要一一对应,不能再两边都出现,recv是跟内存要数据,至于数据的来源无需考虑

 

粘包:

服务端:

import socket
?
server = socket.socket()  # 就比如买了一个手机
server.bind(("127.0.0.1",8088))  # bind中绑定的是IP地址和端口号,注意是一个元组,就比如,将手机卡,插入了手机
server.listen(5)  # 半连接池,最大等待连接数为5个,就比如开机
conn,address = server.accept()  # 接听电话等着别人给你打电话
?
date = conn.recv(1024)  # 听别人说话,接收1023个字节数
print(date)
date = conn.recv(1024)  # 听别人说话,接收1023个字节数
print(date)
?
?
conn.close()  # 挂断电话
server.close()  # 关机

 

客户端:

import socket
?
client = socket.socket()  #拿电话
client.connect(("127.0.0.1",8088))  #绑定的是IP地址和端口号,也是一个元组 拨号
?
client.send(b"hello")  # 对别人发消息
client.send(b"hello")  # 对别人发消息
?
?
client.close()  # 挂电话

 

服务端打印结果:

bhellohello

 

 

这是因为tcp协议会将时间间隔短的,和文件大小小的会一次打包发送给对方

 

 

解决粘包问题:

struct模块:

import struct
?
?
print("--------------------------1--------------------------")
msg = "asdasdasdasdasd"
print("原字符串的长度")
print(len(msg))
?
handler = struct.pack("i",len(msg))
print("创建报头的长度")
print(len(handler))
?
?
res = struct.unpack("i",handler)[0]
print("解报头过后的长度")
print(res)
?
?
?
?
?
print("--------------------------2--------------------------")
?
msg1 = "asdasdasdasdasdasdasdasd"
print("原字符串的长度")
print(len(msg1))
?
handler1 = struct.pack("i",len(msg1))
print("创建报头的长度")
print(len(handler1))
?
?
res1 = struct.unpack("i",handler1)[0]
print("解报头过后的长度")
print(res1)
?
"""
--------------------------1--------------------------
原字符串的长度
15
创建报头的长度
4
解报头过后的长度
15
--------------------------2--------------------------
原字符串的长度
24
创建报头的长度
4
解报头过后的长度
24
"""

 

 

我们可以将报头发过去,然后解报头,就可以知道原来数据的大小,如果这个字节大小比我们接受的大,我们就可以一直让它接收,直到接收完成为止,

服务端:

import json
import os
import socket
import struct

server_path = r/Users/mac/Documents/client-server/server_movie

server = socket.socket()

ip_port = (127.0.0.1, 8080)

server.bind(ip_port)

server.listen(5)

conn, addr = server.accept()
while 1:

    head_len = conn.recv(4)

    head_len = struct.unpack(i, head_len)[0]

    json_head = conn.recv(head_len).decode(utf-8)

    head = json.loads(json_head)

    file_size = head[file_size]

    with open(os.path.join(server_path, head[file_name]), wb) as f:
        while file_size:
            if file_size >= 1024:
                content = conn.recv(1024)
                f.write(content)
                file_size -= 1024
            else:
                content = conn.recv(file_size)
                f.write(content)
                break

 

 

 

 

客户端:

import os
import socket
import json
import struct

client = socket.socket()

ip_port = (127.0.0.1, 8080)

client.connect(ip_port)

head = {
    file_path: r/Users/mac/Documents/client-server/client_movie,
    file_name: None,
    file_size: None
}
movie_list = os.listdir(head[file_path])

while 1:
    for i, m in enumerate(movie_list, 1):
        print(%s --> %s % (i, m))
    choice = input(please input movie number:>>).strip()
    if choice.isdigit():
        choice = int(choice)
        if choice in range(1, len(movie_list) + 1):
            movie_name = movie_list[choice - 1]
            head[file_name] = movie_name
            head[file_size] = os.path.getsize(os.path.join(head[file_path], head[file_name]))
            json_head = json.dumps(head).encode(utf-8)
            bytes_head = len(json_head)
            pack_head = struct.pack(i, bytes_head)
            client.send(pack_head)
            client.send(json_head)
            file_size = head[file_size]
            with open(os.path.join(head[file_path], head[file_name]), rb) as f:
                while file_size:
                    if file_size >= 1024:
                        content = f.read(1024)
                        client.send(content)
                        file_size -= 1024
                    else:
                        content = f.read(file_size)
                        client.send(content)
                        print("finish")
                        break
        else:
            print(index out of range)
    else:
        print(input number...)

 

python基础--socket套接字、粘包问题

标签:port   class   注意   lse   NPU   python基础   col   字符串   ack   

原文地址:https://www.cnblogs.com/tulintao/p/11318594.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!