• 计算机基础知识32


    Socket抽象层(socket编程)

    # Socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单     的接口供应用层调用已实现进程在网络中通信

    socket () 对象

    bind () 函数来绑定

    listen () 监听,等别人电话

    accept()接收,已发送真实数据,真正等待客户端发信息

    read()接收,真正拿到客户端信息  recv

    write()send过程,发送,回应客户端

    read()不会立刻断掉

    close()断开

    # socket抽象层把复杂的事已做比如(三次握手四次挥手),我们不需要操心,只需简单的      发送和接收

    基于TCP协议的套接字(socket)编程

    基于文件类型的套接字家族:
        # 套接字家族的名字:AF_UNIX

    基于网络类型的套接字家族:
        # 套接字家族的名字:AF_INET

    客户端先发送消息,需要服务端先运行起来

    """服务端代码:"""

    1. import socket # 导入socket模块
    2. from socket import AF_INET
    3. server=socket.socket(family=AF_INET, type=socket.SOCK_STREAM)
    4. # AF_INET, type=SOCK_DGRAM: 基于UDP协议的
    5. server.bind(('127.0.0.1', 8000)) # 绑定IP地址和port
    6. # 绑定谁,谁就是服务端,可用你的客户端给他的服务端发信息
    7. server.listen(3) # 服务端做监听,也称为是半链接池(服务端能够同时等待客户端的数量)
    8. sock, addr = server.accept() # sock:当前链接的客户端的链接, addr:就是客户端的地址:ip,port
    9. data=sock.recv(1024) # 接收的数据类型是bytes类型,二进制的 1024 代表接收的最多的字节数
    10. print("接收客户端的数据:",data)
    11. sock.send(data.upper()) # 发送的数据是字节类型的
    12. sock.close() # 关闭链接
    13. server.close()

    # sock, addr = server.accept() 代码会卡住,等待客户端开发链接和发送信息

    """客户端代码"""

    1. import socket
    2. from socket import AF_INET
    3. client=socket.socket(family=AF_INET, type=socket.SOCK_STREAM)
    4. # socket.socket()
    5. client.connect(('127.0.0.1', 8000))
    6. # 开始给服务端发送消息
    7. client.send('hello'.encode('utf-8'))
    8. # 接收服务端发来的消息
    9. data=client.recv(1024)
    10. print("服务端发来的消息:", data)
    11. client.close()

    加上通信和通信循环

    1. """服务端"""
    2. import socket
    3. from socket import AF_INET
    4. server=socket.socket(family=AF_INET, type=socket.SOCK_STREAM)
    5. server.bind(('127.0.0.1', 8000))
    6. server.listen(3)
    7. while True:
    8. sock, addr = server.accept()
    9. while True:
    10. try:
    11. data=sock.recv(1024)
    12. print("接收客户端的数据:",data)
    13. sock.send(data.upper())
    14. except Exception as e:
    15. print(e) # 答应出错误
    16. break
    17. sock.close()
    18. server.close()
    1. """客户端"""
    2. import socket
    3. from socket import AF_INET
    4. client=socket.socket(family=AF_INET, type=socket.SOCK_STREAM)
    5. client.connect(('127.0.0.1', 8000))
    6. while True:
    7. send_data = input('请输入你要发送给服务端的数据:')
    8. client.send(send_data.encode('utf-8'))
    9. data=client.recv(1024) # 接收服务端发来的消息
    10. print("服务端发来的消息:", data)
    11. client.close()

    1、在accept()用while True循环,可支持多个客户端的数据(一个服务端)

    2、当前:客户端只能说一句话

          在send()用while循环,把发送的信息用input写活,可以多次发送信息了

    3、问题:客户端还可以发送信息,但是此时服务端接收一个就已经close

          在第一个close之前再一次循环,accept下

    4、客户端发送的数据是空时,一个客户端出现了问题,整个服务器都将会报错

          用异常捕捉,try

    基于UDP协议的套接字编程

    """服务端"""

    1. import socket
    2. server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 数据报协议-》UDP
    3. server.bind(('127.0.0.1', 8080))
    4. while True:
    5. """client_addr: 客户端的地址"""
    6. data, client_addr = server.recvfrom(1024) # 接收的最大字节数
    7. print('===>', data, client_addr)
    8. server.sendto(data.upper(), client_addr)
    9. server.close()

    """客户端"""

    1. import socket
    2. client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 数据报协议-》UDP
    3. while True:
    4. msg = input('>>: ').strip() # msg=''
    5. client.sendto(msg.encode('utf-8'), ('127.0.0.1', 8080))
    6. data, server_addr = client.recvfrom(1024)
    7. print(data)
    8. client.close()

    粘包现象

    1. import subprocess
    2. res = subprocess.Propen(tasklist,shell=True,stderr=subprocess.PIPE,stdout=subprocess.PIPE)
    3. # shell脚本(linux)
    4. # tasklist命令,其实它是一个shell语言,bash解释器
    5. # 正确stderr=subprocess.PIPE,错误stdout=subprocess.PIPE

    # 粘包:管道里的数据没有取完,造成数据的丢失,但是可以多次取

    # 在内存一定的情况下解决粘包问题:

            1、知道服务端发过来字节的大小/每次接收的字节大小=总次数

            2、struct模块

    1. import struct
    2. res = struct.pack('i',1024) # 1024给打包
    3. print(res) # b'\x00\xo4\xoo... 二进制
    4. print(len(res)) # 4 不管输入多大,固定长度还是4

    # 解包

    1. res1 = struct.unpack('i',res)
    2. print(res1[0]) # 1024

    过程:1、把服务端发过来字节打包,长度4

               2、客户端  sock.recv(4) 只接4个

               3、unpack('i',res)  解包/大小

               4、得到总次数

    TCP的流式协议

    1. sock,addr = sever.accept()
    2. print('jerry',encode('utf-8'))

    在短时间内,短时间客户端可发送多个数据,服务端可以一次性接收完

    今日思维导图:

  • 相关阅读:
    leetcode 901. Online Stock Span(在线库存跨度)
    微软在Microsoft Build 2024 上 发布了.NET 9 预览版4
    [需求管理-1]:IT需求管理总体流程+需求管理需要的技能
    5分钟搞懂MySQL - 行转列
    嵌入式::时钟分析::FOC三环频率
    便捷生活,从便民平台开始
    数据库直连提示 No suitable driver found for jdbc:postgresql
    pycharm
    信息系统开发工程师面试笔记(技术一面)
    PPOCR车牌定位模型推理后处理优化研究
  • 原文地址:https://blog.csdn.net/qq_48064830/article/details/133858624