zoukankan      html  css  js  c++  java
  • 从入门到自闭之--网络编程

    概念:

    1. C/S架构:

      1. C:client 客户端
      2. S: server 服务端,为所有的用户提供服务
    2. B/S架构:只要在浏览器输入网址就可以直接使用了

      1. B:browser 浏览器
      2. S: server 服务端
    3. B/S更好:更节省资源,不用更新,不依赖环境,

      • 统一了所有的web程序入口
    4. C/S架构:安全性,程序比较庞大

    mac地址:

    ​ 是一个物理地址,在网卡中存在的,唯一的标识你的网络设备

    1. mac IP地址:定位到一台机器
    2. port 端口:0-65535,标识一台机器上的一个服务
    3. IP+ port 能够唯一标识一台设备

    ip地址:

    1. 是一个逻辑地址
    2. 是可以根据你的位置变化发生改变的
    3. 能够在广域网中快速的定位你
    4. 几个特殊IP
      1. 127.0.0.1 本地回环地址
      2. 0.0.0.0 表示你的所有网卡地址,标识本机回环地址+内网地址+公网地址

    公网和内网

    1. 公网ip:你能够在任意一个地方去访问的ip地址(不包含保留字段)
      1. ip v4:4位点分十进制组成0.0.0.0~255.255.255.255
      2. IP v6:6位冒分十六进制0:0:0:0:0:0~FFFF:FFFF:FFFF:FFFF:FFFF:FFFF
    2. 内网:只能在一个区域内使用,除了这个区域就无法使用
      1. 所有的内网ip都要使用保留字段
      2. 192.168.0.0--192.168.255.255
      3. 10.0.0.0-10.255.255.255
      4. 172.16.0.0-172.31.255.255

    路由器和交换机:

    1. 交换机:完成局域网内通信

      • 通过ip找mac地址:arp协议,只用到广播和单播

    • 广播
    • 单播
    • 组播
    1. 路由器:完成局域网间通信(网关)

      1. 网关:所有与局域网外部通信的时候所过的关口,所有的请求都会在这里换上网关IP对外通信
    2. 子网掩码(了解):255.255.255.0

      • ip 和子网掩码 按位于运算(0或者1)
      • 可以判断要寻找的机器是不是在一个局域网中
    3. 端口号:

      3306  mysql 数据库
      6379  redis端口
      5000  flask端口
      

    TCP实时通信

    ##server
    
    import socket
    
    sk = socket.socket()
    sk.bind(("127.0.0.1",9043))
    sk.listen()
    conn,addr = sk.accept()
    conn.send(b'hi')
    msg = conn.recv(1024).decode("utf-8")
    print(msg)
    conn.close()
    sk.close()
    
    ```Python
    ##client
    
    import socket
    
    sk = socket.socket()
    
    sk.connect(("127.0.0.1",9043))
    
    msg = sk.recv(1024).decode("utf-8")
    print(msg)
    sk.send("傻子".encode("utf-8"))
    sk.close()
    ```
    

    网络概念补充:

    1. osi七层协议

      1. 应用层
      2. 表示层
      3. 会话层
      4. 传输层
      5. 网络层
      6. 数据链路层
      7. 物理层
    2. osi五层协议:

      1. 应用层
      2. 传输层 #端口 TCP/UDP
      3. 网络层 # IP 路由器
      4. 数据链路层 # mac,arp协议,网卡和交换机
      5. 物理层

    1. TCP/IP--网络层arp

    TCP:

    ​ 上传,下载,邮件,可靠,面向连接,速度慢,能传递的数据长度不限

    1. 两边需要先连接

      • 三次握手

        第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。
        第二次握手:Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态。
        第三次握手:Client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。

    2. 消息传递:(主要看发送,连接时的状态)

    3. 断开连接

      • 四次挥手

        (第一次挥手
        当客户端向服务端请求断开,这时会发送fin的标记报文。
        第二次挥手
        当服务端收到客户端fin断开报文时候,可能正在处理数据,此时服务端会发生ack报文。
        第三次挥手
        当服务端处理完成后,会再次向客户端发送FIN报文,此时可以断开连接。
        第四次挥手
        当客户端收到服务端的fin报文,会向服务端发送确认ACK,经过两个msl《Maximum Segment Lifetime》时长后断开连接。)

    UDP:

    ​ 即时通讯软件,不可靠,面向数据报,速度快,能传递的数据长度有限

    1. 支持一对一,一对多,多对多
    

    粘包:

    ​ 当多条消息发送时接受变成了一条或者出现接收不准确的情况

    1. 粘包现象会发生在发送端

      1. 两条或多条消息间隔时间短,长度短,就会把两条消息在发送之前就拼在一起
      2. 节省每一次发送消息回复的网络资源
    2. 粘包现象会发生在接收端

      1. 多条消息发送到缓存端,但没有被及时接收,或者接收的长度不足一次发送的长度
      2. 数据与数据之间没有边界
    3. 本质:发送的每一条数据之间没有边界

    4. 步骤:

      1. 计算要发送的数据字节长度

      2. 把字结的长度变成4字节,借助struct

            1. 计算要发送的数据字节长度
            2. 把字节的长度变成4字节
            3. 发送这4个字节
            4. 发送数据
        
        1. 服务端

      1. 客户端:
    

    1. 验证客户端的合法性:

      1. 客户端:
      import socket
      import hashlib
      SECRET_KEY = b'alexbigs'
      
      def check_client():
          randbytes = sk.recv(32)
          md5 = hashlib.md5(SECRET_KEY)
          md5.update(randbytes)
          code = md5.hexdigest().encode('utf-8')
          sk.send(code)
      sk = socket.socket()
      sk.connect(('127.0.0.1',9001))
      check_client()
      print('正常的客户端通信')
      
      1. 服务端:
      import os
      import socket
      import hashlib
      SECRET_KEY = b'alexbigsb'
      
      def check_client(conn):
          randbytes = os.urandom(32)
          conn.send(randbytes)
      
          md5 = hashlib.md5(SECRET_KEY)
          md5.update(randbytes)
          code = md5.hexdigest()
          code_cli = conn.recv(32).decode('utf-8')
          return code == code_cli
      
      sk = socket.socket()
      sk.bind(('127.0.0.1',9001))
      sk.listen()
      while True:
          conn,addr = sk.accept()
          if not check_client(conn):continue
          print('进程正常的通信了')
      
      # import os
      # import hmac  # hashlib==hmac
      # randbytes = os.urandom(32)
      # mac = hmac.new(SECRET_KEY,randbytes)
      # ret = mac.digest()
      # print(ret)
      
    2. 并发的socket

      1. 模块socketserver -- 上层模块.

        客户端
        import socket
        
        sk = socket.socket()
        sk.connect(('127.0.0.1',9001))
        
        while True:
            ret = sk.recv(1024)
            print(ret)
        
        import time
        import socket
        
        sk = socket.socket()
        sk.bind(('127.0.0.1',9001))
        sk.listen()
        
        while True:
            conn,addr = sk.accept()
            n = 0
            while True:
                conn.send(str(n).encode('utf-8'))
                n+=1
                time.sleep(0.5)
        
  • 相关阅读:
    通过一个程序来理解PHP里面的抽象类【1】
    mycheckpoint 把玩手记
    Mysql 大量 unauthenticated user
    零基础学习Oracle 10G视频教程
    mysql show processlist命令 详解
    c# 中的事件
    c# 中方法签名 指的是?
    c# 中的索引
    介绍如何使用C#中的委托
    C# 语法学习笔记
  • 原文地址:https://www.cnblogs.com/heyulong1214/p/12069949.html
Copyright © 2011-2022 走看看