zoukankan      html  css  js  c++  java
  • day 24 socket 黏包

    socket 套接字的使用:

    tcp是基于链接的,必须先启动服务端,然后再启动客户端去链接服务端

    server 端

    import socket
    sk = socket.socket()  # 实例化一个socket的sk对象
    sk.bind(('127.0.0.1', 10010))  # 设置IP和端口号
    sk.listen()  # 监听链接
    conn, addr  = sk.accept()  # 接收客户端链接
    
    conn.send('你好'.encode())  # conn.send(b'alex')  向客户端发送信息
    # 如果服务器是发送,客户端要对应使用接收
    ret = conn.recv(1024).decode()  # 接收客户端信息
    # 服务器是接收,客户端要对应发送
    print(ret)  # 打印客户端信息
    conn.close()  # 关闭客户端套接字
    sk.close()  # 关闭服务器套接字

    client 端

    import socket
    sk = socket.socket()  #实例化一个socket的sk对象
    sk.connect(('127.0.0.1', 10010))  # 设置ip和端口号,必须和服务器端相同
    ret = sk.recv(1024).decode()  #接收时要设置长度
    print(ret)    # 打印接收的信息
    sk.send('我好'.encode())    # 发送信息给服务器端
    sk.close()

    UDP 链接:

    server端

    import socket
    udp_sk = socket.socket(type=socket.SOCK_DGRAM)   #创建一个服务器的套接字
    udp_sk.bind(('127.0.0.1',9000))        #绑定服务器套接字
    msg,addr = udp_sk.recvfrom(1024)
    print(msg)
    udp_sk.sendto(b'hi',addr)                 # 对话(接收与发送)
    udp_sk.close()                         # 关闭服务器套接字

    client端

    import socket
    ip_port=('127.0.0.1',9000)
    udp_sk=socket.socket(type=socket.SOCK_DGRAM)
    udp_sk.sendto(b'hello',ip_port)
    back_msg,addr=udp_sk.recvfrom(1024)
    print(back_msg.decode('utf-8'),addr)

    带退出功能的聊天

    # server端:
     import socket
    sk = socket.socket()
    sk.bind(('127.0.0.1', 11111))
    sk.listen()
    conn, addr = sk.accept()
    while True:
        msg = input('>>>: ')
        conn.send(msg.encode())
        if msg == 'q': break
        ret = conn.recv(1024).decode()
        if ret ==  'q':break
        print(ret)
    conn.close()
    sk.close()
    
    
    # client端
    import socket
    sk = socket.socket()
    sk.connect(('127.0.0.1', 11111))
    while True:
        ret = sk.recv(1024).decode()
        print(ret)
        if ret == 'q': break
        msg1 = input('>>>>: ')
        sk.send(msg1.encode())
        if msg1 == 'q': break
    sk.close()

    同步服务器时间:

    #  server 端:
    
    import socket
    import time
    sk = socket.socket()
    sk.bind(('127.0.0.1', 10010))
    sk.listen()
    conn, addr = sk.accept()
    ret = conn.recv(1204).decode()
    str_time = time.strftime(ret)
    conn.send(str_time.encode())
    conn.close()
    sk.close()
    
    # client端 
    import socket
    sk = socket.socket()
    sk.connect(('192.168.13.50', 10010))
    time_type = '%Y-%m-%d'
    sk.send(time_type.encode('utf-8'))
    msg = sk.recv(1024)
    print(msg)
    sk.close()

    黏包:

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

    # 发送一个 ‘hello’, 然后在发送一个‘world’
    # 接收方接收到的是‘helloworld’
    # 这就叫黏包

    发送到的黏包

    接收端的黏包

    1.发送端的粘包  合包机制 + 缓存区
    2.接收端的粘包 延迟接受 + 缓存区

    总结

    黏包现象只发生在tcp协议中:

    1.从表面上看,黏包问题主要是因为发送方和接收方的缓存机制、tcp协议面向流通信的特点。

    2.实际上,主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的

    黏包的解决方法:

    # 告诉客户端,你发送的数据长度
    # server端
    
    import struct
    import socket
    
    sk = socket.socket()
    sk.bind(('127.0.0.1',9000))
    sk.listen()
    
    conn,addr = sk.accept()
    send_msg = input('>>>').encode()
    bytes_len = struct.pack('i', len(send_msg))
    conn.send(bytes_len)
    conn.send(send_msg)   # 粘包现象
    conn.send(b'world')
    conn.close()
    sk.close()
    # client 端
    
    import struct
    import socket
    
    sk = socket.socket()
    sk.connect(('127.0.0.1',9000))
    bytes_len = sk.recv(4)
    msg_len = struct.unpack('i',bytes_len)[0]
    msg = sk.recv(msg_len)
    print(msg.decode())
    msg2 = sk.recv(5)
    print(msg2)
    sk.close()

     补充:

    1.两个连续的send就会发生粘包
    2.用struct自定义协议可以解决粘包问题
    3.什么情况下我们不需要解决粘包 : 文件的传输
    4.自定义协议的进阶版本
    先发送字符串的长度,再发送字符串
    先发送json的长度,再发送json,json的字典中包含着下一条信息的长度,然后按照长度接收
  • 相关阅读:
    dpkg: error processing package XXX (--configure) 解决方法 (ubuntu右上角红色警告)
    overlay2 在打包发布流水线中的应用
    别总写代码,这130个网站比涨工资都重要
    csv 导出变成字符串
    mysql 报错 invalid data source name
    win10 phpredis扩展安装
    redis启动命令
    IDEA Plugins:Easycode(代码生成)安装及使用
    mysql设置自动更新时间
    IDEA快捷键之for循环
  • 原文地址:https://www.cnblogs.com/echo2019/p/10304341.html
Copyright © 2011-2022 走看看