socket加入循环和粘包问题


socket

socket加入通信循环

客户端

import socket

soc = socket.socket()
soc.connect(('127.0.0.1', 8080))

while True:
    inp = input('请输入要发送的信息>>>')
    soc.send(inp.encode('utf-8'))

服务端

import socket

soc = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
soc.bind(('127.0.0.1', 8080))
soc.listen(5)
conn, addr = soc.accept()

while True:
    try:
        data = conn.recv(1024)
        print(data)
    except Exception:
        conn.close()
        break

soc.close()

socket加入连接循环

客户端

import socket

soc = socket.socket()
soc.connect(('127.0.0.1', 8080))

while True:
    inp = input('请输入要发送的消息>>>')
    soc.send(inp.encode('utf-8'))

服务端

import socket

soc = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
soc.bind(('127.0.0.1', 8080))
soc.listen(5)

while True:
    print('等待客户端连接...')
    conn, addr = soc.accept()
    print(f'客户端{addr}已连接上了')
    
    while True:
        try:
            data = conn.recv(1024)
            print(data)
        except Exception:
            break
            
    conn.close()
    
soc.close()

ssh

ssh是远程执行命令

subprocess是执行系统命令的模块

import subprocess

# 执行系统dir命令,把执行的正确结果放到管道中
obj = subprocess.Popen('dir',shell=True,stdout=subprocess.PIPE)
# 拿到正确结果的管道,读出里面的内容
content = obj.stdout.read()
# 因为windows是用gbk编码的,所以要用gbk解码
print(str(content,encoding='gbk'))

粘包问题

粘包现象

客户端

import socket

soc = socket.socket()
soc.connect(('127.0.0.1', 8080))

while True:
    inp = input('请输入要发送的消息>>>')
    soc.send(b'a')
    soc.send(b'b')
    soc.send(b'c')

服务端

import socket

soc = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
soc.bind(('127.0.0.1', 8080))
soc.listen(5)

while True:
    print('等待客户端连接...')
    conn, addr = soc.accept()
    print(f'客户端{addr}已连接上了')
    
    while True:
        try:
            data1 = conn.recv(1024)
            print(data1)
            data2 = conn.recv(1024)
            print(data2)
            data3 = conn,recv(1024)
            print(data3)
        except Exception:
            break
            
    conn.close()
    
soc.close()

客户端发送a、b、c的消息时,服务端有时候会接收到好几个值,而不是单个的a、b、c,这个就是粘包问题。

注意:只有TCP有粘包现象,UDP永远不会粘包

因为TCP协议是基于数据流的,所以收发的消息是不能为空的;但是UDP协议是基于数据报的,即使发送了空内容,UDP协议也会封装上消息头,因此也不会是空内容。

解决粘包问题的方法

给我们要发送的消息加上自定义长度报头,报头中包含我们要发送消息的长度,接收消息的时候,先从读取固定长度的报头,然后再读取真实的长度。

客户端

import json
import socket
import struct

client = socket.socket()
client.connect(('127.0.0.1', 8080))
while True:
    content = input('开始接收信息>>>')
    head_len = struct.unpack('i', client.recv(4))[0]
    dic = json.loads(client.recv(head_len))
    size_len = dic['size']
    name = dic['name']
    count = 0
    data = b''
    with open(name, 'wb') as fw:
        while count < size_len:
            if size_len < 1024:
                data_temp = client.recv(size_len)
            else:
                if size_len - count >= 1024:
                    data_temp = client.recv(1024)
                else:
                    data_temp = client.recv(size_len - count)
                    
            data = data_temp
            count += len(data_temp)
            
        f.write(data)
        
    print('接收完成')
    
client.close()

服务端

import os
import json
import socket
import struct

server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind(('127.0.0.1', 8080))
server.listen(5)

while True:
    conn, addr = server.accept()
    
    while True:
        dic = {'size': os.path.getsize('run.py'), 'name': 'new_run.py'}
        dic_bytes = bytes(json.dumps(dic), 'utf-8')
        dic_bytes_len = len(dic)
        head = struct.pack('i', dic_bytes_len)
        
        conn.send(head)
        conn.send(dic_bytes)
        with open('run.py', 'rb') as fr:
            for line in fr:
                conn.send(line)
                
    conn.close()
    
server.close()
优质内容筛选与推荐>>
1、CYQ.Data 轻量数据层之路 优雅V1.4 现世 附API帮助文档(九)
2、Bzoj3224 / Tyvj 1728 普通替罪羊树
3、探路以太坊
4、C# Enum设计和使用的相关技巧
5、加分二叉树


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号