ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

day32 连接/通信循环和粘包问题

2019-09-06 20:52:00  阅读:178  来源: 互联网

标签:soc socket day32 粘包 print data 连接 conn 客户端


连接循环/通信循环

话不多说,直接上代码

# server.py

import socket
#生成一个socket对象
soc=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#绑定地址跟端口号
soc.bind(('127.0.0.1',8001))
#监听(半连接池的大小),不是连接数
soc.listen(3)
#等着客户端来连接,conn相当于连接通道,addr是客户端的地址
while True:
    print('等待客户端连接')
    conn,addr=soc.accept()    #卡主,如果没有客户端连接,会一直卡在这,当有连接,才继续往下走
    print('有个客户端连接上了',addr)
    while True:
        try:
            #windows如果客户端断开,会报错,加了try
            #linux如果客户端,断开,不会报错,会收到空,所有当data为空时,也break
            #等待接收,最大收取1024个字节
            data=conn.recv(1024)    #会卡主,当客户端有数据过来,才会执行
            if len(data)==0:  #处理linux客户端断开,如果在window下这段代码根本不会执行(即便是客服端发了空,这个地方也不会走到)
                break
            print(data)
        except Exception:

            break
    # 关闭通道
    conn.close()

# 关闭套接字
soc.close()
# client.py

import socket

soc=socket.socket()

soc.connect(('127.0.0.1',8001))
while True:
    in_s=input('请输入要发送的数据:')
    #发送的数据必须是b格式,in_s.encode('utf-8')  把字符串编码成b格式
    #把b格式转成字符串
    # ss=str(b'hello',encoding='utf-8')
    # ss=b'hello'.decode('utf-8')
    # #把字符串转成b格式
    # by=bytes('hello',encoding='utf-8')
    # by='hello'.encode('utf-8')


    soc.send(in_s.encode('utf-8'))

粘包问题

粘包:tcp会把数据量较小,时间间隔较短的数据,当做同一个包发送

# server.py

import socket
#生成一个socket对象
soc=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#绑定地址跟端口号
soc.bind(('127.0.0.1',8001))
#监听(半连接池的大小),不是连接数
soc.listen(3)
#等着客户端来连接,conn相当于连接通道,addr是客户端的地址
while True:
    print('等待客户端连接')
    conn,addr=soc.accept()    #卡主,如果没有客户端连接,会一直卡在这,当有连接,才继续往下走
    print('有个客户端连接上了',addr)
    while True:
        try:
            data=conn.recv(1024)
            print(data)
            data2=conn.recv(1024)
            print(data2)
            data3=conn.recv(1024)
            print(data3)
        except Exception:

            break
    # 关闭通道
    conn.close()

# 关闭套接字
soc.close()
# client.py

import socket

soc=socket.socket()

soc.connect(('127.0.0.1',8001))
while True:
    in_s=input('请输入要发送的数据:')
    soc.send(b'a')
    soc.send(b'b')
    soc.send(b'c')

模拟ssh功能

# server.py

import socket
import subprocess
soc=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
soc.bind(('127.0.0.1',8001))
soc.listen(3)
while True:
    print('等待客户端连接')
    conn,addr=soc.accept()
    print('有个客户端连接上了',addr)
    while True:
        try:
            data=conn.recv(1024)
            if len(data)==0:
                break
            print(data)
            obj = subprocess.Popen(str(data,encoding='utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            #执行正确的结果 b 格式,gbk编码(windows平台)
            msg=obj.stdout.read()
            #把执行的结果通过网络传给c端
            conn.send(msg)
        except Exception:

            break
    # 关闭通道
    conn.close()

# 关闭套接字
soc.close()
# clinet.py

import socket

soc=socket.socket()

soc.connect(('127.0.0.1',8001))
while True:
    in_s=input('请输入要执行的命令:')
    soc.send(in_s.encode('utf-8'))
    data=soc.recv(1024)
    print(str(data,encoding='gbk'))

#粘包:tcp会把数据量较小,时间间隔较短的数据,当做同一个包发送

解决粘包终极版

# server.py

import socket
import subprocess
import struct
soc=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
soc.bind(('127.0.0.1',8001))
soc.listen(3)
while True:
    print('等待客户端连接')
    conn,addr=soc.accept()
    print('有个客户端连接上了',addr)
    while True:
        try:
            data=conn.recv(1024)
            if len(data)==0:
                break
            print(data)
            obj = subprocess.Popen(str(data,encoding='utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            #执行正确的结果 b 格式,gbk编码(windows平台)
            msg=obj.stdout.read()

            #发送的时候需要先把长度计算出来
            #头必须是固定长度
            #先发4位,头的长度
            import json
            dic={'size':len(msg)}
            dic_bytes=(json.dumps(dic)).encode('utf-8')
            #head_count是4个字节的长度
            head_count=struct.pack('i',len(dic_bytes))
            print(dic)
            conn.send(head_count)
            #发送头部内容
            conn.send(dic_bytes)
            #发了内容
            conn.send(msg)
        except Exception:

            break
    # 关闭通道
    conn.close()

# 关闭套接字
soc.close()
# client.py

import socket
import struct
import json
soc=socket.socket()

soc.connect(('127.0.0.1',8001))
while True:
    in_s=input('请输入要执行的命令:')
    soc.send(in_s.encode('utf-8'))
    #头部字典的长度
    head_dic_len=soc.recv(4)
    #解出真正的长度
    head_l=struct.unpack('i',head_dic_len)[0]
    #byte 字典的长度
    #收真正的头部字典
    dic_byte=soc.recv(head_l)
    head=json.loads(dic_byte)
    print(head)
    l=head['size']
    count=0
    data_total=b''
    print(l)
    while count<l:
        if l<1024: #如果接受的数据小于1024 ,直接接受数据大小
            data=soc.recv(l)
        else:#如果接受的数据大于1024
            if l-count>=1024: #总数据长度-count(目前收到多少,count就是多少) 如果还大于1024  ,在收1024
                data=soc.recv(1024)
            else: #总数据长度-count(目前收到多少,count就是多少) 如果小于1024,只收剩下的部分就可
                data=soc.recv(l-count)

        data_total+=data
        count+=len(data)

    print(str(data_total,encoding='gbk'))

标签:soc,socket,day32,粘包,print,data,连接,conn,客户端
来源: https://www.cnblogs.com/17vv/p/11478146.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有