zoukankan      html  css  js  c++  java
  • 8.23_python_lx_day30

    一.TCP基本语法

    import socket

    (1)服务端

    <1>创建一个socket对象

    sk = socket.socket()

    <2>绑定对应的ip和端口号(让其他主机在网络中可以找得到)

    #127.0.0.1代表本地ip
    sk.bind( ("127.0.0.1",9001) )

    <3>开启监听

    sk.listen()

    <4>建立三次握手

    conn,addr = sk.accept()

    <5>处理收发数据的逻辑

    #recv 接收 send 发送
    res = conn.recv(1024) # 代表一次最多接收1024个字节
    print(res.decode('utf-8'))

    <6>四次挥手

    conn.close()

    <7>退还端口

    sk.close()

    (2)客户端

    <1>创建一个socket对象

    sk = socket.socket()

    <2>与服务器建立连接

    sk.connect(   ('127.0.0.1',9001)  )

    <3>发送数据(只能发送二进制的字节流)

    sk.send('需要发送的字符串'.encode('utf-8'))

    <4>关闭连接

    sk.close()

    二.TCP循环发送消息

    (1)服务端

    <1>创建一个socket对象

    sk = socket.socket()

    <2>绑定对应的ip和端口号(让其他主机在网络中可以找得到)

    #127.0.0.1代表本地ip
    sk.bind( ("127.0.0.1",9001) )

    <3>开启监听

    sk.listen()

    <5>处理收发数据的逻辑

    while True:
        #<4>三次握手
        conn,addr = sk.accept()
        while True:
            res = conn.recv(1024)
            print(res.decode())
            strvar = input("请输入服务端要给客户端发送的内容")
            conn.send(strvar.encode())
            if strvar.upper() == "Q":
                break

    <6>四次挥手

    conn.close()

    <7>退还端口

    sk.close()

    (2)客户端

    <1>.创建socket对象

    sk = socket.socket()

    <2>连接服务端

    sk.connect( ("127.0.0.1" , 9000) )

    <3>收发数据

    while True:
        strvar = input("请输入您要发送的内容:")
        sk.send(strvar.encode())
        res = sk.recv(1024)
        if res == b"q" or res == b"Q":
            break
        print(res.decode())

    <4>关闭连接

    sk.close()

    三.udp基本语法

    (1)服务端

    <1>创建udp对象

    sk = socket.socket(type=socket.SOCK_DGRAM)

    <2>绑定地址端口号

    sk.bind( ("127.0.0.1",9000) )

    <3>udp服务器,在一开始只能够接受数据

    msg,cli_addr = sk.recvfrom(1024)
    print(msg.decode())
    print(cli_addr)
    # 服务端给客户端发送数据
    msg = "发送的字符串"
    sk.sendto(msg.encode(),cli_addr)

    <4>关闭连接

    sk.close()

    (2)客户端

    <1>创建udp对象

    sk = socket.socket(type = socket.SOCK_DGRAM)

    <2>收发数据的逻辑

    # 发送数据
    msg = "你好,你是mm还是gg"
    # sendto( 消息,(ip,端口号) )
    sk.sendto( msg.encode() ,  ("127.0.0.1",9000)  )
    # 接受数据
    msg,server_addr = sk.recvfrom(1024)
    print(msg.decode())
    print(server_addr)

    <3>关闭连接

    sk.close()

    四.udp循环发消息

    (1)服务端

    <1>创建udp对象

    sk = socket.socket(type=socket.SOCK_DGRAM)

    <2>绑定地址端口号

    sk.bind( ("127.0.0.1",9000) )

    <3>udp服务器,在一开始只能够接受数据

    while True:
        # 接受消息
        msg,cli_addr = sk.recvfrom(1024)
        print(msg.decode())
        message = input("服务端给客户端发送的消息是?:")
        # 发送数据
        sk.sendto(message.encode() , cli_addr)

    <4>关闭连接

    sk.close()

    五.黏包

    • 黏包出现的两种情况:
      •     (1) 发送端发送数据太快
      •   (2) 接收端接收数据太慢

    (1)struct

    • pack :
    •   把任意长度数字转化成具有固定4个字节长度的字节流
    • unpack :
    •   把4个字节值恢复成原来的数字,返回最终的是元组
    import struct
    # pack
    # i => int 要转化的当前数据是整型
    # pack 的范围 -2147483648 ~ 2147483647 21个亿左右
    res = struct.pack("i",2100000000)
    print(res , len(res)) # len(res) => 4
    
    # unpack
    # i => 把对应的数据转换成int整型
    tup = struct.unpack("i",res)
    print(tup) # (2100000000,)
    print(tup[0]) #2100000000
    • 解决黏包场景:
    •   应用场景在实时通讯时,需要阅读此次发的消息是什么
    • 不需要解决黏包场景:
    •   下载或者上传文件的时候,最后要把包都结合在一起,黏包无所谓

    (2)使用struct解决黏包问题

    <1>服务端

    import socket
    import struct
    sk = socket.socket()
    sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    sk.bind( ("127.0.0.1",9000) )
    sk.listen()
    conn,addr = sk.accept()
    # 处理收发数据的逻辑
    strvar = input("请输入你要发送的数据")
    msg = strvar.encode()
    length = len(msg)
    res = struct.pack("i",length)
    # 第一次发送的是字节长度
    conn.send(res)
    # 第二次发送真实的数据
    conn.send(msg)
    # 第三次发送真实的数据
    conn.send("世界真美好123".encode())
    conn.close()
    sk.close()

    <2>客户端

    import socketimport struct
    sk = socket.socket()
    sk.connect( ("127.0.0.1",9000) )
    # 处理收发数据的逻辑
    # 第一次接受的是字节长度
    n = sk.recv(4)
    tup = struct.unpack("i",n)
    n = tup[0]
    # 第二次接受真实的数据
    res = sk.recv(n)
    print(res.decode())
    # 第三次接受真实的数据
    res = sk.recv(1024)
    print(res.decode())
    sk.close()
  • 相关阅读:
    OpenJDK源码研究笔记(十二):JDBC中的元数据,数据库元数据(DatabaseMetaData),参数元数据(ParameterMetaData),结果集元数据(ResultSetMetaDa
    Java实现 LeetCode 257 二叉树的所有路径
    Java实现 LeetCode 257 二叉树的所有路径
    Java实现 LeetCode 257 二叉树的所有路径
    Java实现 LeetCode 242 有效的字母异位词
    Java实现 LeetCode 242 有效的字母异位词
    Java实现 LeetCode 242 有效的字母异位词
    Java实现 LeetCode 241 为运算表达式设计优先级
    Java实现 LeetCode 241 为运算表达式设计优先级
    Java实现 LeetCode 241 为运算表达式设计优先级
  • 原文地址:https://www.cnblogs.com/Magicianlx/p/13551569.html
Copyright © 2011-2022 走看看