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

本文详细介绍TCP/IP网络编程的基础知识,包括IP地址与端口号的概念、通信流程、socket及TCP协议的工作原理。并通过Python实例演示了客户端和服务端程序的开发过程,最后展示了如何利用多线程技术实现一个可以同时处理多个客户端请求的服务端程序。
摘要由CSDN通过智能技术生成


前言

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)

      参数名说明
      AddressFamilyIP地址类型,分为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提供了大量能使我们快速便捷地处理数据的函数和方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值