网络编程(粘包)

cmd 运行一些命令
  dir - - 查看文件目录
  ipconfig - - 查看ip
  tasklist - - 查看Windows上开了哪些服务
  tasklist | findstr 程序 - - 是否有要查看的程序
  cd 目录 - -- 跳到该目录下

import subprocess   # 解决执行命令
obj = subprocess.Popen("ipconfig /all",shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
# shell--windows的解释器
# stdout(标准正确输出)--正确的命令下:把输出的结果暂时放到"管道"里
# stderr(标准错误输出)--错误的命令下:把输出的结果暂时放到"管道"里
# stdin(标准正确输入)
stdout = obj.stdout.read().decode("gbk")    # 从管道拿出来,得到bytes类型
print(stdout)

stderr = obj.stderr.read().decode("gbk")    # 从管道拿出来,得到bytes类型
print(stderr)

;  -- 分割多个命令

import subprocess
obj1 = subprocess.Popen("tasklist",shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
obj2 = subprocess.Popen("findatr pycharm",shell=True,stdin=obj1.stdout,stdout=subprocess.PIPE)
print(obj2.stdout.read().decode("gbk")
tcp协议--流式协议
粘包--在接收端粘包,也可能在发送端粘包


struct模块
该模块可以把一个类型,如数字,转成固定长度的bytes

#'i' format requires -2147483648 <= number <= 2147483647 #这个是范围

import struct
res = struct.pack("i",123)  # 打包成bytes
# struct.pack("i",123)  i--针对int类型
print(res)

ret = struct.unpack("i",res)  # 解包,返回元组,第一个值就是原值
print(ret)

 

struct模块的模式:




import socket
import subprocess
import struct
import json
# 买手机
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

# 绑定手机卡
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #在bind前加,重新启用ip地址
phone.bind(("192.168.11.48",8088))#--127.0.0.1--默认自己的地址

# 开机
phone.listen(5)#--最大挂起的连接数

# 等电话连接
print("starting...")
while True: #连接循环
    conn,addr = phone.accept()  #接收
    print("IP:%s,PORT:%s"%(addr[0],addr[1]))    #打印一个ip地址和创建的端口地址

    # 收发消息
    while True:#通信循环
        try:
            cmd = conn.recv(1024) #--最大收到1024,受限于内存
            if not cmd:break   #当输入的内容为空时跳出循环,针对Linux系统

            # 执行命令
            obj = subprocess.Popen(cmd.decode("utf-8"),
                                   shell=True,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
            stdout = obj.stdout.read()
            stderr = obj.stderr.read()

            # 制作报头
            header_dic = {"filename":"a.txt",
                          "totoal_size":len(stdout)+len(stderr),
                          "md5":"adfd123adsf"}
            header_josn = json.dumps(header_dic)
            header_bytes = header_josn.encode("utf-8")

            # 先发报头的长度
            conn.send(struct.pack("i",len(header_bytes)))

            # 发送报头
            conn.send(header_bytes)

            # 发送真实数据
            conn.send(stdout)
            conn.send(stderr)

        except Exception:   #当输入的内容为空时跳出循环,针对Windows系统
            break

    # 断开连接
    conn.close()

# 关机
phone.close()
服务端
import socket
import struct
import json
# 买手机
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

# 打电话
phone.connect(("192.168.11.48",8088))   # 发送

# 发收消息
while True: #通信循环
    cmd = input(">>>").strip()  # 不要在客户端执行切换目录的命令
    if not cmd:continue     # 当用户输入的为空的时候,重新输入
    if cmd.lower() == "q":break
    phone.send(cmd.encode("utf-8"))

    # 先收报头的长度
    obj = phone.recv(4)
    header_size = struct.unpack("i",obj)[0]

    # 再收报头
    header_bytes = phone.recv(header_size)
    header_json = header_bytes.decode("utf-8")
    header_dic = json.loads(header_json)
    print(header_dic)

    # 循环接收真实的数据
    totoal_size = header_dic["totoal_size"]
    totoal_data = b""
    recv_size = 0
    while recv_size < totoal_size:
        recv_data = phone.recv(1024)
        totoal_data += recv_data
        recv_size += len(recv_data)

    print(totoal_data.decode("gbk"))

# 断开连接
phone.close()
客户端

 

 
posted @ 2017-09-26 16:30  chitalu  阅读(81)  评论(0)    收藏  举报