UDP、TCP 和 多任务(线程) 之间的使用

一 、基础知识点

UDP、TCP 和 多任务(线程) 之间的使用_第1张图片UDP、TCP 和 多任务(线程) 之间的使用_第2张图片

二、习题演练

1. 多任务版udp聊天器

目标:使用多线程完成多任务,实现聊天器收发小时同时进行

说明:

编写一个有2个线程的程序
线程1用来接收数据然后显示
线程2用来检测键盘数据然后通过udp发送数据
要求
实现上述要求
总结多任务程序的特点

参考代码:
import socket
import threading

发送数据的功能函数
    def send_msg(udp_socket):
    # 接收用户输入的数据
    send_content = input("请输入您要发送的数据:")
    # 对数据进行gbk编码
    send_data = send_content.encode("gbk")
    # 接收对方的ip地址和端口号
    dest_ip = input("请输入对方的ip地址:")
    dest_port = int(input("请输入对方的端口号:"))
    # 发送数据
    udp_socket.sendto(send_data, (dest_ip, dest_port))
接收数据的功能函数
    def recv_msg(udp_socket):
    	while True:
        	# 接收数据 1024:表示每次接收数据的最大字节数
        	recv_data, ip_port = udp_socket.recvfrom(1024)
        	# 解码数据
        	recv_content = recv_data.decode("gbk")
        	print(recv_content, ip_port)
主函数
	if __name__ == '__main__':
    # 创建udpsocket
    udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    # 绑定端口, 提示:客户端不强制要求绑定端口
    # 在同一个电脑上端口号不能重复
    udp_socket.bind(("", 8080))
    # 创建接收数据的线程
    recv_thread = threading.Thread(target=recv_msg, args=(udp_socket,))
    # 设置成为守护主线程,主线程退出后子线程直接销毁
    recv_thread.setDaemon(True)
    recv_thread.start()

    while True:
        # 接收用户的指令
        option = input("请输入功能选项 1. 发送 2. 退出:")
        if option == "1":
            # 发送数据
            send_msg(udp_socket)

        elif option == "3":
            break

    # 关闭socket
    udp_socket.close()

2.多任务版TCP服务端

目标:知道使用多线程实现多个客户端同时连接服务端

功能要求:使用多任务实现多个客户端同时连接TCP服务端.

参考代码:
import socket
import threading

接收客户端信息
    def recv_msg(service_client_socket, ip_port):
    	while True:
        	# 接收客户端的数据
        	recv_data = service_client_socket.recv(1024)
	        if recv_data:
	            # 解码
	            recv_content = recv_data.decode("gbk")
	            print(recv_content)
	            service_client_socket.send("ok,问题正在处理中....".encode("gbk"))
	        else:
	            print(ip_port, "客户端断开连接了")
	            break
	    # 终止和客户端的通信
	    service_client_socket.close()
主函数
	if __name__ == '__main__':
    # 创建tcp服务端socket
    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(("", 7891))
    # 设置监听,把主动套接字改变被动套接字,只能接收客户端的连接请求
    tcp_server_socket.listen(128)
    # 循环接收客户端的连接请求
    while True:
        # 接收客户端的连接请求
        service_client_socket, ip_port = tcp_server_socket.accept()
        print(ip_port)

        # 创建接收数据的子线程
        recv_thread = threading.Thread(target=recv_msg, args=(service_client_socket, ip_port))
        # 设置守护主线程,主线程退出子线程直接销毁
        recv_thread.setDaemon(True)
        # 启动接收数据的子线程
        recv_thread.start()
    # 关闭服务端socket,不接收客户端的连接请求
    tcp_server_socket.close()

3.多任务版文件下载器

目标:知道使用多线程实现多个客户端同时下载文件

功能要求:使用多任务实现多个客户端同时连接TCP服务端下载文件

参考代码:
import socket
import os
import threading
import time

(1) 多任务版文件下载器服务端代码

下载文件函数
	def download_file(service_client_socket):
	    # 代码执行到说明解阻塞,说明连接建立成功
	    file_name_data = service_client_socket.recv(1024)
	    # 解码数据
	    file_name = file_name_data.decode("gbk")
	    print(file_name, ip_port)
	    if os.path.exists(file_name):
	        # 文件存在
	        with open(file_name, "rb") as file:
	            # 读取文件数据
	            while True:
	                file_data = file.read(1024)
	                if file_data:
	                    # 发送文件数据给客户端
	                    service_client_socket.send(file_data)
	                    time.sleep(1)
	                else:
	                    break
	    else:
	        print("文件不存在")
	    # 终止和客户端服务
	    service_client_socket.close()
主函数
	if __name__ == '__main__':
	    # 创建tcp服务端socket
	    tcp_serve_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	    # 设置socket选项,防止程序退出端口不立即释放的问题
	    tcp_serve_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
	    # 绑定端口
	    tcp_serve_socket.bind(("", 9090))
	    # 设置监听,把主动套接字改成被动套接字,被动套接字只能接收客户端的连接请求,不能收发消息
	    tcp_serve_socket.listen(128)
	    # 循环接收客户端的连接请求, 提示:现在的下载是同步下载,一个用户下载完成以后另外一个用户才能下载
	    while True:
	        # 接收客户端的连接请求
	        service_client_socket, ip_port = tcp_serve_socket.accept()
	        # 开辟线程
	        sub_thread = threading.Thread(target=download_file, args=(service_client_socket, ))
	        sub_thread.start()
	
	    # 终止提供处理连接请的服务
	    tcp_serve_socket.close()

(2) 多任务版文件下载器客户端代码

import socket

if __name__ == '__main__':
    # 创建tcp客户端socket
    tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 建立连接
    tcp_client_socket.connect(("192.168.199.161", 9090))
    # 获取用户输入文件名
    file_name = input("请输入您要下载的文件名:")
    # 使用gbk进行编码
    file_name_data = file_name.encode("gbk")
    # 代码执行到此,说明连接建立成功
    tcp_client_socket.send(file_name_data)
    with open("/home/python/Desktop/" + file_name, "wb") as file:
        # 循环接收服务端发送的文件二进制数据
        while True:
            # 获取服务端文件数据
            file_data = tcp_client_socket.recv(1024)
            if file_data:
                # 写入到指定文件
                file.write(file_data)
            else:
                break

    # 关闭socket
    tcp_client_socket.close()

你可能感兴趣的:(UDP、TCP 和 多任务(线程) 之间的使用)