zoukankan      html  css  js  c++  java
  • 网络编程小结

    软件开发架构

    C/S架构

    client:客户端

    server:服务端

    优点:软件的使用稳定,网络资源占用少

    缺点:

    • 若需要使用多个软件,需要下载多个客户端
    • 服务端更新后,用户也需要跟着下载更新

    B/S架构

    browser:浏览器

    server:服务端

    优点:以浏览器充当客户端,服务端更新不需要用户更新下载

    缺点: 占用网络资源大,网络不好时,体验差

    互联网OSI七层协议

    从下往上分为:

    物理层--> 数据链路层--> 网络层--> 传输层--> 会话层--> 表示层--> 应用层

    物理层

    传输电信号 0100011

    数据链路层

    1. 规定好电信号的分组方式

    2. 必须要由一块网卡

    3. mac地址:12位唯一的16进制数

      ​ 前6位是厂商号

      ​ 后6位是流水号

    4. 以太网协议:

      • 在同一个局域网内通信
        • 单播 1对1吼
        • 广播 多对多吼
        • 会有广播风暴, 不能对局域网通信

    网络层

    ip:定位局域网位置

    port: 端口,唯一标识一台计算机上的一个程序

    arp协议:将mac地址获取,并解析成ipi地址

    传输层

    TCP协议

    TCP协议称之为流式协议

    若想要通信,必须建立连接,并建立双向通道

    三次握手,四次挥手:

    • 三次握手建立连接
      • 客户端往服务端发送建立通道
      • 服务端要确认客户端的请求,并往客户端也发送请求建立通道
      • 客户端接收到服务端建立连接的请求,并返回确认
      • 建立双向通道
    • 双向通道
      • 反馈机制
      • 客户端往服务端发送请求获取数据,服务端务必返回数据,客户端确认收到,否则会反复发送,一直到某个时间段内,会停止发送
    • 四次挥手断连接
      • 客户端往服务端发送断开连接请求,服务端返回确认收到
      • 服务端需要再次发送断开连接请求
      • 客户端返回确认收到
      • 最终确认断开来连接

    UDP协议

    1. 数据不安全
    2. 不需要建立双向通道
    3. 传输速度快
    4. 不会由粘包问题
    5. 客户端发送数据,不需要服务端确认收到

    应用层

    ftp、http

    socket套接字

    socket用来写套接字客户端与服务端的模块,内部帮我们封装好了7层协议需要做的事情.

    socket套接字模板

    # 服务端
    import socket
    
    server = socket.socket()
    server.bind(
        ('127.0.0.1', 9527)
    )
    
    server.listen(5)
    
    while True:
        conn, addr = server.accept()
        print(addr)
    
        while True:
            try:
                data = conn.recv(1024)
                if len(data) == 0:
                    continue
    
                print(data.decode('utf-8'))
                conn.send(data)
    
            except Exception as e:
                print(e)
                break
    
        conn.close()
       
    
    # 客户端
    import socket
    
    client = socket.socket()
    client.connect(
        ('127.0.0.1', 9527)
    )
    
    while True:
        send_msg = input('客户端:')
        client.send(send_msg.encode('utf-8'))
        data = client.recv(1024)
        print(data.decode('utf-8'))
    

    subprocess

    用来通过代码往cmd创建一个管道,并且发送命令和接收cmd返回的结果

    # 伪代码:
    import subprocess
    obj = subprocess.Popen(
        '命令',
        shell=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE
    )
    msg = obj.stdout.read() + obj.stderr.read()
    
    

    粘包问题

    1. 不能确定对方发送数据的大小
    2. 在短时间内,间隔时间短,并且数据量小的情况下,默认将这些数据打包成一个多次发送的数据,然后一次性发送

    struct解决粘包问题

    可以将一个数据的长度打包成一个固定长度的报头.
    struct.pack('模式i', '源数据长度')
    data = 'gagawagwaga'
    # 打包成报头
    headers = struct.pack('i', len(data))
    
    # 解包获取数据真实长度
    data = struct.unpack('i', headers)[0]
    
    # 服务端
    import socket
    import subprocess
    import struct
    
    server = socket.socket()
    server.bind(
        ('127.0.0.1', 9527)
    )
    
    server.listen(5)
    
    while True:
        conn, addr = server.accept()
        print(addr)
    
        while True:
            try:
                cmd = conn.recv(1024).decode('utf-8')
                if len(cmd) == 0:
                    continue
    
                obj = subprocess.Popen(
                    cmd,
                    shell=True,
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE
                )
    
                res = obj.stdout.read() + obj.stderr.read()
    
                headers = struct.pack('i', len(res))
                conn.send(headers)
                conn.send(res)
    
    
            except Exception as e:
                print(e)
                break
    
        conn.close()
        
        
    # 客户端
    import socket
    import struct
    
    
    client = socket.socket()
    client.connect(
        ('127.0.0.1', 9527)
    )
    
    while True:
        cmd = input('客户端输入命令:')
        client.send(cmd.encode('utf-8'))
    
        headers = client.recv(4)
        data_len = struct.unpack('i', headers)[0]
        data= client.recv(data_len)
        print(data.decode('gbk'))
    
    

    升级版: 先将数据存放到字典中,将字典打包发送过去

    字典的好处:真实数据长度;文件的描述信息;发送的数据更小

    socketserver

    # 服务端
    import socketserver
    class MyTCPServer(socketserver.BaseRequestHandler):
    
        def handle(self):
            print(self.client_address)
    
            while True:
                try:
                    data = self.request.recv(1024).decode('utf-8')
                    send_msg = data.upper()
                    self.request.send(send_msg.encode('utf-8'))
    
                except Exception as e:
                    print(e)
                    break
    
    if __name__ == '__main__':
        server = socketserver.ThreadingTCPServer(
            ('127.0.0.1', 9527), MyTCPServer
        )
        server.serve_forever()
    
  • 相关阅读:
    Pycharm软件更换pip默认安装源为国内安装源
    电商网站名词item>SKU与SPU
    Linux通过端口号查看使用进程结束进程
    window系统下的pycharm对虚拟机中的Ubuntu系统操作MySQL数据库
    JAVA项目常用的异常处理情况总结
    公文流转系统(未完成)
    《程序员修炼之道》读后感(三)
    Java文件操作递归遍历文件目录
    Java Web初试连接数据库完成学生信息录入
    JavaJFrame窗口实现新课程添加
  • 原文地址:https://www.cnblogs.com/setcreed/p/11748688.html
Copyright © 2011-2022 走看看