• python 网络编程:socket(二)


    上节地址:Python网络编程:socket

    一、send和sendall区别

    send,sendall
            ret = send('safagsgdsegsdgew') #send 发送完成后会有一个返回值,告知发送了多少,并不一定会把数据全部发送过去。
            sendall:内部调用send,将数据全部发送完为止。
            因此我们使用时最好使用sendall

    二、粘包 

    粘包问题需要理解recv()的使用,我们定义接收值的时候会写recv(1024)表示一次接收1024字节,但是有时候接收的数据大于1024字节,这样socket默认变不发送了,等待下次接收其他命令时在将上次没有发送完的数据继续发送过去,这样就形成了粘包问题。对于粘包,可以在正式收发数据之前先判断下数据的大小,然后分片发送。下面是利用socket和subprocess实现的类似cmd的程序,在cmd执行一些命令时,如ipconfig,会因为输出内容过长而造成粘包问题。下面的例子是解决粘包之后的。观察粘包现象的版本就不在提供了。
    #!/usr/bin/env python
    # _*_ coding:utf_8 _*_
    import socket
    ip_port=('127.0.0.1',9002)
    s = socket.socket()
    s.connect(ip_port)
    while True:
        send_data = input('>>: ').strip()
        if len(send_data) == 0:continue
        if send_data == 'exit':break
        s.send(bytes(send_data,encoding='utf-8'))
        #解决粘包问题
        ready_tag = s.recv(1024)  #收取待发送字节的长度
        ready_tag=str(ready_tag,encoding='utf8')
        if ready_tag.startswith('Ready'):  #数据包格式为Ready|9124
            msg_size=int(ready_tag.split('|')[-1])
        start_tag = 'Start'
        s.sendall(bytes(start_tag,encoding='utf8'))  #发送消息,表示开始传输
        recv_size = 0
        #print(msg_size)
        recv_msg = b''
        while recv_size < msg_size:
            recv_data = s.recv(1024)
            recv_msg+=recv_data
            recv_size+=len(recv_data)
        print(str(recv_msg,encoding='utf8'))
        #收消息
        # recv_data=s.recv(1024)
        # print(str(recv_data,encoding='utf-8'))
    
    s.close()
    socket_client
    #!/use/bin/env python
    #_*_ coding:utf_8 _*_
    import socket
    import subprocess
    ip_addr=('127.0.0.1',9002)
    s=socket.socket()   #创建对象
    s.bind(ip_addr)     #绑定连接地址
    s.listen(5)         #设置监听主机数
    while True:
        conn,addr=s.accept()
        i = 0
        while True:
            print(i)
            try:
                recv_data = conn.recv(1024)
                print('------0')
                #print(str(recv_data,encoding='utf-8'))
                if len(recv_data) == 0:break
                #执行系统命令
                p=subprocess.Popen(str(recv_data,encoding='utf-8'),shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)#执行系统命令,windows平台命令的标准输出是gbk编码,需要转换
                res = p.stdout.read() #获取标准输出
                if len(res) == 0:   #执行错误命令,send_data为空
                    send_data = str(p.stderr.read(),encoding='utf-8')
                else:
                    send_data=str(res,encoding='gbk')
                send_data=bytes(send_data,encoding='utf-8')    #要发送的数据
    
                #判断粘包
                ready_tag='Ready|%s' %len(send_data)
                conn.send(bytes(ready_tag,encoding='utf8')) #发送数据长度
                feedback=conn.recv(1024)  #接收确认信息
                feedback=str(feedback,encoding='utf8')
                if feedback.startswith('Start'):
                    print(send_data)
                    conn.sendall(send_data)  #发送命令的执行结果
                #conn.sendall(send_data)
                print('succeed')
                i+=1
    
    
    
            except Exception:
                break
        conn.close()
    socket cmd
  • 相关阅读:
    wp8.1 Study14 FilePicker简单介绍
    wp8.1 Study13:在WP8.1中分享文件和数据
    WP8.1 Study12:文件压缩与Known Folder(包含SD卡操作)
    wp8.1 Study9:针对不同的屏幕和手机方向调整UI
    wp8.1 Study11:APP里文件读写和使用XML和Json序列化
    wp8.1 Study10:APP数据存储
    wp8.1 C#技巧: 计时器
    wp8.1 Study8:页面过渡和主题动画(Page transition and Theme animations)
    2、IValueConverter应用
    1、ViewModel类的构建和INoyifyPropertyChanged的应用
  • 原文地址:https://www.cnblogs.com/ernest-zhang/p/5660590.html
Copyright © 2020-2023  润新知