Linux学习笔记(3)- 网络编程以及范例程序


前言

TCP/IP网络编程基础知识可参见1.https://blog.csdn.net/weixin_42048417/article/details/80459671?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-0&spm=1001.2101.3001.4242

网络介绍

网络的概念

实现资源共享和信息传递的虚拟平台

目的

编写基于网络通信的软件或程序

socket编程,web编程

IP地址的介绍

def: 分配给网络设备上网使用的数字标签,它能够标识网络中唯一的一台设备,好比现实生活中每个人都有一个手机号。

表现形式 为 IPv4 IPv6

作用,通过IP地址找到网络中唯一一台设备。

  1. ifconfig 查看网卡信息
  2. ping 检查网络是否正常

可在终端输入检测和了解

端口和端口号的介绍

只有ip地址是无法将信息进行传输的

每运行一个软件都有一个对应的端口,端口都对应一个端口号

端口号有65536个

通信流程

通过IP地址找到对应的设备,通过端口号找到对应的端口,然后通过端口把数据给应用程序。

端口是传输数据通道,是数据传输的必经之路

端口号是用来管理区分不同端口的一个号码

  • 端口号的分类

    • 知名端口号

      众所周知的端口号,0-1023;比如 21给ftp,25给SMTP等

    • 动态端口号

      开发应用程序使用端口号,1024-65535

socket介绍

IP地址+端口号+工具(socket)

socket(简称 套接字)网络数据通讯的工具

TCP介绍

在发送数据之前要选择网络传输方式(传输协议),保证程序之间按照指定的传输规定进行数据的通信。

Transmission Control Protocol 简称传输控制协议,是一种面向连接的、可靠的、基于字节流的传输层通信协议

char1 面向连接

  • 通信步骤:(类似于打电话,在通信开始前要建立连接,才能发送数据,通信结束要关闭连接)
    1. 创建连接(双方为此连接分配必要的资源来记录连接的状态和信息)
    2. 传输数据
    3. 关闭连接(释放系统资源)

char2 可靠性

  • TCP采用发送应答机制
    • 每个报文段都必须接到对方的应答
  • 超时重传
    • 启动定时器
  • 错误校验
    • 校验和函数
  • 流量控制和阻塞管理
    • 避免发送端发送过快使得接收方来不及接收

python3编码转换

  1. 网络传输是以二进制数据进行传输的
  2. encode 编码 将字符串转换为字节码
  3. decode 解码 将字节串转换为字符码
    1. bytes.encode(encoding = “utf-8”)
    2. str.encode(encoding = “utf-8”)

TCP客户端程序开发流程

TCP客户端程序开发 运行在用户设备上的程序

TCP服务端程序开发 运行在服务器设备上的程序,专门为客户端提供数据服务

流程图

在这里插入图片描述

  • 客户端开发流程
    1. 创建客户端套接字对象(买电话)
    2. 和服务端套接字建立连接(打电话)
    3. 发送数据
    4. 接收数据
    5. 关闭客户端套接字(挂电话)

知识要点

  • TCP网络应用程序开发分为 客户端程序开发服务端程序开发
  • 主动发起建立连接请求的是客户端程序
  • 等待接受连接请求的是服务端程序

范例 :

  • socket类的介绍

    1. 导入socket模块

      import socket

    2. 创建客户端socket对象

      socket.socket(AddressFamily, Type)

      参数名 说明
      AddressFamily IP地址类型,分为IPv4和IPv6 (AF_INET 表示IPV4,
      SOCK_STREAM表示TCP传输协议类型)
      Type 传输协议类型
  • 开发客户端使用到的函数

    方法名 说明
    connect 和服务端套接字建立连接
    send 发送数据 需注意encode编码
    recv 接收数据 需注意decode解码
    close 关闭连接
  • import socket
    
    if __name__ == "__main__":
        # 1. 创建客户端套接字对象(买电话)
        tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 2. 和服务端套接字建立连接(打电话)
        tcp_client_socket.connect(("192.168.99.1",8080))
        # 3. 发送数据
        tcp_client_socket.send("nihaoma".encode(encoding = "utf-8"))
        # 4. 接收数据,阻塞等待数据的到来
        recv_data = tcp_client_socket.recv(1024)
        print(recv_data.decode())
        # 5. 关闭客户端套接字(挂电话)
        tcp_client_socket.close()
    
    #执行结果
    [2021-03-14 22:37:42.270]
    nihaoma
    
    [2021-03-14 22:37:46.730]# SEND ASCII TO ALL>
    http://www.cmsoft.cn
    

    本案例中使用网络调试助手作为TCP服务端,可查看电脑对应的IP地址。网络调试助手下载链接为https://download.csdn.net/download/weixin_43357695/15791548

  • 客户端开发流程

    1. 创建服务端套接字对象
    2. 绑定IP地址和端口号
    3. 设置监听
    4. 等待接收客户端的连接请求
    5. 接收数据
    6. 发送数据
    7. 关闭客户端套接字
  • 范例

    1. socket类的介绍(同客户端)

    2. 开发服务端使用到的函数

      方法名 说明
      blind 绑定IP地址和端口号 元组中第一个元素是ip地址,一般不需要设置,
      第二个是启动程序后使用的端口号
      listens 设置监听,参数为最大等待连接数
      accept 等待接受客户端的连接请求
      send 发送数据 需注意encode编码,要发送的二进制数据
      recv 接收数据 解码成字符串需注意decode解码,参数为每次接受数据的大小,
      单位是字节
    3. import socket
      
      if __name__ == "__main__":
      # 1. 创建服务端套接字对象
          tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
           # 设置端口复用(linux下可能存在再次运行端口被占用的情况)
          tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
      	
      # 2. 绑定IP地址和端口号
      #     tcp_server_socket.bind(("192.168.125.115",8888))
          #若blind的参数第一个ip地址元素为“”,则默认本机IP地址
          tcp_server_socket.bind(("",8888))
      # 3. 设置监听 128:代表服务器中等待排队连接的最大数量
          tcp_server_socket.listen(128)
      # 4. 等待接收客户端的连接请求  accept()阻塞等待,返回一个用以和客户端通信的socket,客户端的地址
          comu_socket, ip_port = tcp_server_socket.accept()
          print("客户端地址:", ip_port)
      # 5. 接收数据
          recv_data = comu_socket.recv(1024)
      #     print("接收到的数据:", recv_data.decode())
          print("接收到的数据:", recv_data.decode('gbk'))#中文解码
      # 6. 发送数据
          comu_socket.send("客户端你的数据我接收到啦".encode("gbk"))
      # 7. 关闭客户端套接字
          comu_socket.close()
          tcp_server_socket.close()
      
      #执行结果
      #网络调试助手
      [2021-03-14 23:37:17.562]# SEND ASCII>
      你好啊
      
      [2021-03-14 23:37:17.600]# RECV ASCII>
      客户端你的数据我接收到啦
      
      #编译器
      >>> %Run '网络编程_服务端开发.py'
      客户端地址: ('192.168.125.115', 3606)
      接收到的数据: 你好啊
      
  • TCP网络应用程序注意点

    1. 当TCP客户端程序想要和TCP服务端斤西瓜通信的时候必须先建立连接
    2. TCP客户端一般不要绑定端口号,因为客户端时主动发起建立连接的
    3. TCP服务端必须绑定端口号,否则客户端找不到这个TCP服务端程序
    4. listen后的套接字是被动套接字,只负责接收新的客户端的连接请求,不能收发消息
    5. 当TCP客户端程序和TCP服务端程序连接成功后,TCP服务器程序会产生一个新的套接字,收发客户端消息使用该套接字
    6. 关闭accept返回的套接字意味着和这个客户端已经通信完毕
    7. 当客户端的套接字调用close后,服务端的recv会解阻塞,返回的数据长度为0,服务端可以通过返回数据的长度来判断客户是否有已经下线,反之服务端关闭套接字,客户端的recv也会解阻塞,返回数据长度也为0
  • 知识要点

    1. TCP socket的发送和接收缓冲区

      • 当创建一个TCP socket对象的时候会有一个发送缓冲区和一个接收缓冲区,指内存中一片空间
    2. send是不是直接把数据发给服务端

      • 不是,要想发送数据,必须通过网卡发送数据,应用程序无法直接通过网卡发送数据,它需要调用操作系统接口,也就是说应用程序先把发送的数据写入到发送缓冲区(内存中的一片空间),再有操作系统控制网卡把发送缓冲区的数据发送给服务端网卡
    3. recv是不是直接从客户端接收数据

      • 不是,与send相反,接收缓冲区

      在这里插入图片描述

      发送与接收数据都是由网卡完成的。

多任务版TCP服务器程序开发

一个服务端服务多个客户端

步骤分析:

  1. 编写一个TCP服务端程序,循环等待接收客户端的连接请求

    • import socket
      
      if __name__ == "__main__":
      # 1. 创建服务端套接字对象
          tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
           # 设置端口复用(linux下可能存在再次运行端口被占用的情况)
          tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
      	
      # 2. 绑定IP地址和端口号
      #     tcp_server_socket.bind(("192.168.125.115",8888))
          #若blind的参数第一个ip地址元素为“”,则默认本机IP地址
          tcp_server_socket.bind(("",8888))
      # 3. 设置监听 128:代表服务器中等待排队连接的最大数量
          tcp_server_socket.listen(128)
          while True:#循环等待客户端的连接请求
          # 4. 等待接收客户端的连接请求  accept()阻塞等待,返回一个用以和客户端通信的socket,客户端的地址
              comu_socket, ip_port = tcp_server_socket.accept()
              print("客户端地址:", ip_port)
          # 5. 接收数据
              recv_data = comu_socket.recv(1024)
          #     print("接收到的数据:", recv_data.decode())
              print("接收到的数据:", recv_data.decode('gbk'))#中文解码
          # 6. 发送数据
              comu_socket.send("客户端你的数据我接收到啦".encode("gbk"))
          # 7. 关闭客户端套接字
              comu_socket.close()
              
          tcp_server_socket.close()
      
  2. 第一步不能实现同时服务多个客户端,联系多任务(进程与线程)

    当客户端和服务端建立连接成功,创建子线程,使用子线程专门处理客户端的请求,防止主线程阻塞

    在这里插入图片描述

    import socket
    import threading
    
    #处理客户端函数
    def  handle_client(comu_socket):
        # 5. 接收数据
            recv_data = comu_socket.recv(1024)
        #     print("接收到的数据:", recv_data.decode())
            print("接收到的数据:", recv_data.decode('gbk'))#中文解码
        # 6. 发送数据
            comu_socket.send("客户端你的数据我接收到啦".encode("gbk"))
        # 7. 关闭客户端套接字
            comu_socket.close()
    
    if __name__ == "__main__":
    # 1. 创建服务端套接字对象
        tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
         # 设置端口复用(linux下可能存在再次运行端口被占用的情况)
        tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
    	
    # 2. 绑定IP地址和端口号
    #     tcp_server_socket.bind(("192.168.125.115",8888))
        #若blind的参数第一个ip地址元素为“”,则默认本机IP地址
        tcp_server_socket.bind(("",8888))
    # 3. 设置监听 128:代表服务器中等待排队连接的最大数量
        tcp_server_socket.listen(128)
        while True:
        # 4. 等待接收客户端的连接请求  accept()阻塞等待,返回一个用以和客户端通信的socket,客户端的地址
            comu_socket, ip_port = tcp_server_socket.accept()
            print("客户端地址:", ip_port)  
        # 使用多线程去接受多个客户端的请求
            sub_thread = threading.Thread(target = handle_client, args = (comu_socket,))
            sub_thread.start()
            
        tcp_server_socket.close()
    
    

    执行结果:

    %Run '多任务版服务端.py'(同时打开多个网络调试助手进行连接和传输)
    客户端地址: ('192.168.125.116', 16764)
    接收到的数据: http://www.cmsoft.cn
    客户端地址: ('192.168.125.116', 16774)
    客户端地址: ('192.168.125.116', 16778)
    接收到的数据: 2222
    客户端地址: ('192.168.125.116', 16800)
    接收到的数据: 3333
    接收到的数据: 2222
    

总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

猜你喜欢

转载自blog.csdn.net/weixin_43357695/article/details/114852622