【Python进阶】第7篇:TCP和socket客户端程序开发。总结md文档集合(已分享,附代码)

举报
程序员一诺112 发表于 2023/11/28 19:20:02 2023/11/28
【摘要】 本文从14大模块展示了python高级用的应用。分别有Linux命令,多任务编程、网络编程、Http协议和静态Web编程、html+css、JavaScript、jQuery、MySql数据库的各种用法、python的闭包和装饰器、mini-web框架、正则表达式等相关文章的详细讲述。

本文从14大模块展示了python高级用的应用。分别有Linux命令,多任务编程、网络编程、Http协议和静态Web编程、html+css、JavaScript、jQuery、MySql数据库的各种用法、python的闭包和装饰器、mini-web框架、正则表达式等相关文章的详细讲述。


全套笔记和代码自取地址: 请移步这里

感兴趣的小伙伴可以自取哦,欢迎大家点赞转发~



共 14 章,157 子模块




TCP 客户端程序开发


学习目标

  • 能够写出 TCP 客户端应用程序发送和接收消息



1. 开发 TCP 客户端程序开发步骤回顾


  1. 创建客户端套接字对象

  2. 和服务端套接字建立连接

  3. 发送数据

  4. 接收数据

  5. 关闭客户端套接字


2. socket 类的介绍


导入 socket 模块 import socket

创建客户端 socket 对象 socket.socket(AddressFamily, Type)

参数说明:

  • AddressFamily 表示IP地址类型, 分为TPv4和IPv6

  • Type 表示传输协议类型

方法说明:

  • connect((host, port)) 表示和服务端套接字建立连接, host是服务器ip地址,port是应用程序的端口号

  • send(data) 表示发送数据,data是二进制数据

  • recv(buffersize) 表示接收数据, buffersize是每次接收数据的长度


3. TCP 客户端程序开发示例代码


import socket
​
​
if __name__ == '__main__':
    # 创建tcp客户端套接字
    # 1. AF_INET:表示ipv4
    # 2. SOCK_STREAM: tcp传输协议
    tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 和服务端应用程序建立连接
    tcp_client_socket.connect(("192.168.131.62", 8080))
    # 代码执行到此,说明连接建立成功
    # 准备发送的数据
    send_data = "你好服务端,我是客户端小黑!".encode("gbk")
    # 发送数据
    tcp_client_socket.send(send_data)
    # 接收数据, 这次接收的数据最大字节数是1024
    recv_data = tcp_client_socket.recv(1024)
    # 返回的直接是服务端程序发送的二进制数据
    print(recv_data)
    # 对数据进行解码
    recv_content = recv_data.decode("gbk")
    print("接收服务端的数据为:", recv_content)
    # 关闭套接字
    tcp_client_socket.close()


执行结果:

b'hello'
接收服务端的数据为: hello


说明

  1. str.encode(编码格式) 表示把字符串编码成为二进制

  2. data.decode(编码格式) 表示把二进制解码成为字符串

网络调试助手充当服务端程序:

网络调试助手


4. 小结


  1. 导入socket模块

  2. 创建TCP套接字‘socket’

    • 参数1: ‘AF_INET’, 表示IPv4地址类型

    • 参数2: ‘SOCK_STREAM’, 表示TCP传输协议类型

  3. 发送数据‘send’

    • 参数1: 要发送的二进制数据, 注意: 字符串需要使用encode()方法进行编码

  4. 接收数据‘recv’

    • 参数1: 表示每次接收数据的大小,单位是字节

  5. 关闭套接字‘socket’表示通信完成


TCP服务端程序开发


学习目标

  • 能够写出TCP服务端应用程序接收和发送消息



1. 开发 TCP 服务端程序开发步骤回顾


  1. 创建服务端端套接字对象

  2. 绑定端口号

  3. 设置监听

  4. 等待接受客户端的连接请求

  5. 接收数据

  6. 发送数据

  7. 关闭套接字


2. socket 类的介绍


导入 socket 模块 import socket

创建服务端 socket 对象 socket.socket(AddressFamily, Type)

参数说明:

  • AddressFamily 表示IP地址类型, 分为TPv4和IPv6

  • Type 表示传输协议类型

方法说明:

  • bind((host, port)) 表示绑定端口号, host 是 ip 地址,port 是端口号,ip 地址一般不指定,表示本机的任何一个ip地址都可以。

  • listen (backlog) 表示设置监听,backlog参数表示最大等待建立连接的个数。

  • accept() 表示等待接受客户端的连接请求

  • send(data) 表示发送数据,data 是二进制数据

  • recv(buffersize) 表示接收数据, buffersize 是每次接收数据的长度


3. TCP 服务端程序开发示例代码


import socket
​
if __name__ == '__main__':
    # 创建tcp服务端套接字
    tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 设置端口号复用,让程序退出端口号立即释放
    tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True) 
    # 给程序绑定端口号
    tcp_server_socket.bind(("", 8989))
    # 设置监听
    # 128:最大等待建立连接的个数, 提示: 目前是单任务的服务端,同一时刻只能服务与一个客户端,后续使用多任务能够让服务端同时服务与多个客户端,
    # 不需要让客户端进行等待建立连接
    # listen后的这个套接字只负责接收客户端连接请求,不能收发消息,收发消息使用返回的这个新套接字来完成
    tcp_server_socket.listen(128)
    # 等待客户端建立连接的请求, 只有客户端和服务端建立连接成功代码才会解阻塞,代码才能继续往下执行
    # 1. 专门和客户端通信的套接字: service_client_socket
    # 2. 客户端的ip地址和端口号: ip_port
    service_client_socket, ip_port = tcp_server_socket.accept()
    # 代码执行到此说明连接建立成功
    print("客户端的ip地址和端口号:", ip_port)
    # 接收客户端发送的数据, 这次接收数据的最大字节数是1024
    recv_data = service_client_socket.recv(1024)
    # 数据的长度
    recv_data_length = len(recv_data)
    print("接收数据的长度为:", recv_data_length)
    # 对二进制数据进行解码
    recv_content = recv_data.decode("gbk")
    print("接收客户端的数据为:", recv_content)
    # 准备发送的数据
    send_data = "ok, 问题正在处理中...".encode("gbk")
    # 发送数据给客户端
    service_client_socket.send(send_data)
    # 关闭服务与客户端的套接字, 终止和客户端通信的服务
    service_client_socket.close()
    # 关闭服务端的套接字, 终止和客户端提供建立连接请求的服务
    tcp_server_socket.close()


执行结果:

客户端的ip地址和端口号: ('172.16.47.209', 52472)
接收数据的长度为: 5
接收客户端的数据为: hello


说明:

当客户端和服务端建立连接后,服务端程序退出后端口号不会立即释放,需要等待大概1-2分钟。

解决办法有两种:

  1. 更换服务端端口号

  2. 设置端口号复用(推荐大家使用),也就是说让服务端程序退出后端口号立即释放。

设置端口号复用的代码如下:

  
  
# 参数1: 表示当前套接字
  
  
  
  
# 参数2: 设置端口号复用选项
  
  
  
  
# 参数3: 设置端口号复用选项对应的值
  
  
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)


网络调试助手充当客户端程序:

网络调试助手


4. 小结


  1. 导入socket模块

  2. 创建TCP套接字‘socket’

    • 参数1: ‘AF_INET’, 表示IPv4地址类型

    • 参数2: ‘SOCK_STREAM’, 表示TCP传输协议类型

  3. 绑定端口号‘bind’

    • 参数: 元组, 比如:(ip地址, 端口号)

  4. 设置监听‘listen’

    • 参数: 最大等待建立连接的个数

  5. 等待接受客户端的连接请求‘accept’

  6. 发送数据‘send’

    • 参数: 要发送的二进制数据, 注意: 字符串需要使用encode()方法进行编码

  7. 接收数据‘recv’

    • 参数: 表示每次接收数据的大小,单位是字节,注意: 解码成字符串使用decode()方法

  8. 关闭套接字‘socket’表示通信完成


TCP网络应用程序的注意点


学习目标

  • 能够说出开发TCP网络应用程序的注意点



1. TCP网络应用程序的注意点介绍


  1. 当 TCP 客户端程序想要和 TCP 服务端程序进行通信的时候必须要先建立连接

  2. TCP 客户端程序一般不需要绑定端口号,因为客户端是主动发起建立连接的。

  3. TCP 服务端程序必须绑定端口号,否则客户端找不到这个 TCP 服务端程序。

  4. listen 后的套接字是被动套接字,只负责接收新的客户端的连接请求,不能收发消息。

  5. 当 TCP 客户端程序和 TCP 服务端程序连接成功后, TCP 服务器端程序会产生一个新的套接字,收发客户端消息使用该套接字。

  6. 关闭 accept 返回的套接字意味着和这个客户端已经通信完毕

  7. 关闭 listen 后的套接字意味着服务端的套接字关闭了,会导致新的客户端不能连接服务端,但是之前已经接成功的客户端还能正常通信。

  8. 当客户端的套接字调用 close 后,服务器端的 recv 会解阻塞,返回的数据长度为0,服务端可以通过返回数据的长度来判断客户端是否已经下线,反之服务端关闭套接字,客户端的 recv 也会解阻塞,返回的数据长度也为0


案例-多任务版TCP服务端程序开发


学习目标

  • 能够说出多任务版TCP服务端程序的实现过程



1. 需求


目前我们开发的TCP服务端程序只能服务于一个客户端,如何开发一个多任务版的TCP服务端程序能够服务于多个客户端呢?

完成多任务,可以使用线程,比进程更加节省内存资源。


2. 具体实现步骤


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

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

  3. 把创建的子线程设置成为守护主线程,防止主线程无法退出。


3. 多任务版TCP服务端程序的示例代码:


import socket
import threading
​
​
  
  
# 处理客户端的请求操作
  
  
def handle_client_request(service_client_socket, ip_port):
    # 循环接收客户端发送的数据
    while True:
        # 接收客户端发送的数据
        recv_data = service_client_socket.recv(1024)
        # 容器类型判断是否有数据可以直接使用if语句进行判断,如果容器类型里面有数据表示条件成立,否则条件失败
        # 容器类型: 列表、字典、元组、字符串、set、range、二进制数据
        if recv_data:
            print(recv_data.decode("gbk"), ip_port)
            # 回复
            service_client_socket.send("ok,问题正在处理中...".encode("gbk"))
​
        else:
            print("客户端下线了:", ip_port)
            break
    # 终止和客户端进行通信
    service_client_socket.close()
​
​
if __name__ == '__main__':
    # 创建tcp服务端套接字
    tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 设置端口号复用,让程序退出端口号立即释放
    tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
    # 绑定端口号
    tcp_server_socket.bind(("", 9090))
    # 设置监听, listen后的套接字是被动套接字,只负责接收客户端的连接请求
    tcp_server_socket.listen(128)
    # 循环等待接收客户端的连接请求
    while True:
        # 等待接收客户端的连接请求
        service_client_socket, ip_port = tcp_server_socket.accept()
        print("客户端连接成功:", ip_port)
        # 当客户端和服务端建立连接成功以后,需要创建一个子线程,不同子线程负责接收不同客户端的消息
        sub_thread = threading.Thread(target=handle_client_request, args=(service_client_socket, ip_port))
        # 设置守护主线程
        sub_thread.setDaemon(True)
        # 启动子线程
        sub_thread.start()
​
​
    # tcp服务端套接字可以不需要关闭,因为服务端程序需要一直运行
    # tcp_server_socket.close()


执行结果:

客户端连接成功: ('172.16.47.209', 51528)
客户端连接成功: ('172.16.47.209', 51714)
hello1 ('172.16.47.209', 51528)
hello2 ('172.16.47.209', 51714)



4. 小结


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

while True:
     service_client_socket, ip_port = tcp_server_socket.accept()


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

while True:
     service_client_socket, ip_port = tcp_server_socket.accept() 
     sub_thread = threading.Thread(target=handle_client_request, args=(service_client_socket, ip_port))
     sub_thread.start()


  1. 把创建的子线程设置成为守护主线程,防止主线程无法退出。

while True:
     service_client_socket, ip_port = tcp_server_socket.accept() 
     sub_thread = threading.Thread(target=handle_client_request, args=(service_client_socket, ip_port))
     sub_thread.setDaemon(True) 
     sub_thread.start()




socket之send和recv原理剖析


学习目标

  • 能够知道send和recv的底层工作原理



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


当创建一个TCP socket对象的时候会有一个发送缓冲区和一个接收缓冲区这个发送和接收缓冲区指的就是内存中的一片空间。


2. send原理剖析


send是不是直接把数据发给服务端?

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


3. recv原理剖析


recv是不是直接从客户端接收数据?

不是,应用软件是无法直接通过网卡接收数据的,它需要调用操作系统接口,由操作系统通过网卡接收数据,把接收的数据写入到接收缓冲区(内存中的一片空间),应用程序再从接收缓存区客户端发送的数据


4. send和recv原理剖析图


send和recv原理剖析图

说明:

  • 发送数据是发送到发送缓冲区

  • 接收数据是从接收缓冲区


5. 小结


不管是recv还是send都不是直接接收到对方的数据和发送数据到对方,发送数据会写入到发送缓冲区,接收数据是从接收缓冲区来读取,发送数据和接收数据最终是由操作系统控制网卡来完成。




未完待续, 同学们请等待下一期



感兴趣的小伙伴可以自取哦,欢迎大家点赞转发~

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。