zoukankan      html  css  js  c++  java
  • 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()
    
  • 相关阅读:
    VS10的一个问题
    有关开发的配置的有用信息
    管理Fragments(转)
    消除SDK更新时的“https://dl-ssl.google.com refused”异常--(转)
    JAVA字符串编码转换常用类
    在 Android 中调用二进制可执行程序(native executable )
    Android NDK 下的宽字符编码转换及icu库的使用(转)
    Linux字符编码转换 UTF8转GB3212
    一键生成JNI头文件方法二
    eclipse中创建NDK和JNI开发环境最简单配置方法
  • 原文地址:https://www.cnblogs.com/yunluo/p/11568288.html
Copyright © 2011-2022 走看看