• 2.网络编程基本语法


    网络编程基本语法

    1.TCP基本语法

    服务端
    # 服务端 (七剑下天山)
    """
    注意 :
        一发一收必须成对,否则会出现数据异常
    """
    import socket
    # 1.建立一个TCP(socket)对象
    sk = socket.socket()
    
    # 2.绑定对应的IP和端口号(注册网络,让其他电脑可以访问到该主机)
    sk.bind(("127.0.0.1",8000)) #注意:参数为一个元组
    
    # 3.开启监听(监听是否有设备访问) 
    sk.listen()
    
    # 4.建立连接 (三次握手)
    """
    接收到对象和访问设备的地址:
    addr : ('127.0.0.1', 45466)
    """
    conn,addr = sk.accept()
    
    # 5.处理收发数据的逻辑
    msg = conn.recv(1024) #最多一次接受1024个字节
    print(msg.decode("utf-8")) #需要解码成字符串
    
    # 6.断开连接 (四次挥手)
    conn.close()
    
    # 7.退还端口
    sk.close()
    
    客户端
    # 客户端
    import socket
    
    # 1.建立一个TCP(socket)对象
    sk = socket.socket()
    
    # 2.与服务端建立连接 (需要知道目标主机的IP和端口号)
    sk.connect(("127.0.0.1",8000)) #注意: 一个参数元组
    
    # 3.发送数据 (必须是二进制字节流)
    strvar = "好人一生平安~"
    sk.send(strvar.encode("utf-8"))
    
    # 4.关闭连接
    sk.close()
    

    2.TCP循环发消息

    服务端
    # 循环发消息[服务端]
    import socket
    sk = socket.socket() #建立TCP对象
    sk.bind(("127.0.0.1",8001)) #绑定ip端口注册网络
    sk.listen() #开启监听
    
    while True: #服务端永不停机,一直监听
        conn,addr  = sk.accept() #建立连接(三次招手)
        # 循环发消息
        while True:
            msg = conn.recv(1024) #收消息
            print(msg.decode("utf-8"))
            # 接收q停止循环
            if msg == b"q" or msg == b"Q":
                break
            strvar = input("请输入内容:")
            conn.send(strvar.encode("utf-8")) #发消息
            
        conn.close() #关闭连接 (四次挥手)      
        
    sk.close() #退还端口
    
    客户端
    # 循环发消息[客户端]
    import socket
    
    sk = socket.socket() #建立TCP对象
    sk.connect(("127.0.0.1",8001)) #与服务端建立连接
    
    # 循环发消息
    while True:
        # 发送数据
        strvar = input("请输入您要发送的数据(按q结束):")
        sk.send(strvar.encode()) #
        # 停止循环条件
        if strvar.upper() == "Q":
            break
        # 接收数据
        msg = sk.recv(1024)
        print(msg.decode())
        
    sk.close() #关闭连接
    

    3.UDP 基本语法

    服务端
    # 服务端
    import socket
    
    # 1.建立一个UDP对象
    sk = socket.socket(type = socket.SOCK_DGRAM)
    # 2.绑定IP和端口号
    sk.bind(("127.0.0.1",8002)) #参数一个元组
    # 3.针对udp服务器,第一次只能接受数据
    while True:
        while True:
            msg,addr = sk.recvfrom(1024) #接收访问设备的信息和地址
            if msg ==b"q" or msg ==b"Q":    
                break
            print(msg.decode("utf-8"))
            strvar = input("请输入发送的内容:")
            sk.sendto(strvar.encode("utf-8"),addr) #发送内容
    # 4.关闭连接
    sk.close()
    
    客户端
    # 客户端
    import socket
    
    # 1.建立udp对象
    sk = socket.socket(type = socket.SOCK_DGRAM)
    
    # 2.收发信息的逻辑
    while True:
        strvar = input("请输入您要发送的内容(按q退出):")
        sk.sendto(strvar.encode("utf-8"),("127.0.0.1",8002)) #发送数据
        if strvar.upper() =="Q":
            break
        msg,addr = sk.recvfrom(1024) #接收数据信息和地址
        print(msg.decode("utf-8"))
    
    # 3.关闭连接
    sk.close()
    

    4.tcp黏包

    原因:
    [发送端]出现黏包: 1.数据太小, 2.数据之间时间间隔太短了;
    [接收端]出现黏包: 接受数据太慢了
    
    struct 模块
    """
    pack   打包
    	把任意长度数字转换成具有固定4个字节长度的字节流
    unpack 解包
    	把4个字节长度的值恢复成原来的数字,返回的是数字元组
    """
    # i => int 要转换的当前类型是整型 数字范围-21亿~21亿
    # pack 打包
    res = struct.pack("i",191992131) #打包
    print(res,len(res)) # b'Cx91qx0b' 4
    #unpack 解包成数字元组
    tup = struct.unpack("i",res) #解包成数字元组
    print(tup,type(tup)) #(191992131,) <class 'tuple'>
    res = tup[0] #取出元组数字
    print(res,type(res)) # 191992131 <class 'int'>
    
    解决黏包办法(struct模块)

    服务端 :

    # 服务端
    import socket,struct
    
    sk = socket.socket() #建立对象
    sk.bind(("127.0.0.1",8000)) #绑定IP端口 注册网络
    sk.listen() #打开监听
    conn,addr = sk.accept() #建立连接
    # 发送消息
    strvar = input("请输入你想要发送的数据:")
    msg = strvar.encode() #转化字节流
    num = len(msg) #字节流大小
    res = struct.pack("i",num) #打包4个字节的字节流
    conn.send(res) #先发送数据大小
    conn.send(msg) #再发送真实数据
    
    conn.send("贾英贺".encode("utf-8"))
    
    conn.close() #关闭连接
    sk.close() #退还端口
    

    客户端 :

    # 客户端
    import socket,struct
    
    sk = socket.socket() #建立对象
    sk.connect(("127.0.0.1",8000)) #连接服务端
    # 接收消息
    msg = sk.recv(4) #第一次接收数据大小
    tup = struct.unpack("i",msg) #解包成数字元组
    num = tup[0] #提取数字
    msg1 = sk.recv(num) #第二次接收真实数据,按第一次提取数字大小截取
    print(msg1.decode("utf-8"))
    
    msg2 = sk.recv(1024)
    print(msg2.decode("utf-8"))
    
    sk.close()
    
  • 相关阅读:
    白话LINQ系列2以代码演进方式学习LINQ必备条件
    《Entity Framework 6 Recipes》中文翻译系列 (9) 第二章 实体数据建模基础之继承关系映射TPH
    Linq To Sqlite 一一二二
    《Entity Framework 6 Recipes》中文翻译系列 (10) 第二章 实体数据建模基础之两实体间Isa和Hasa关系建模、嵌入值映射
    《Entity Framework 6 Recipes》中文翻译系列 (14) 第三章 查询之查询中设置默认值和存储过程返回多结果集
    《Entity Framework 6 Recipes》中文翻译系列 (13) 第三章 查询之使用Entity SQL
    白话LINQ系列1什么是LINQ?
    《Entity Framework 6 Recipes》翻译系列 (3) 第二章 实体数据建模基础之创建一个简单的模型
    JS 实现trim()
    mysql表切换引擎的几种方法
  • 原文地址:https://www.cnblogs.com/jia-shu/p/14190621.html
Copyright © 2020-2023  润新知