湖南大学计算机网络实验二------水

计算机网络实验二 网络基础编程实验(Python3)

HNU

由于这一次实验2.1-2.3都是给了代码的,所以没有写了,只写了2.3的对比和2.4的代码,实现互通信

2.3 多线程/线程池对比(python3.5)

  • 多线程:每处理一个socket请求都会新建一个线程 类似于临时工简单的为每一个socket都开一个线程,将socket作为参数传进去即可。优点:合理利用CPU资源。并且可以提高程序的运行效率缺点:如果有大量的线程运行,会消耗大部分内存,会影响性能(可能会死机),CPU需要他们之间的切换线程运行可能会出现死锁、线程安全问题
  • 线程池:提前创建好多个线程,然后需要就从线程池里拿,用完换回去即可 类似于长期工优点:如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程,并且大量线程空闲,就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。这个时候,线程池的作用就出来了,当程序需要创建大量生命周期很短暂的线程时,使用线程池可以有效控制系统中并发线程的数量,线程池中,一个线程于空闲状态时,可以被使用,使用时变为阻塞状态,使用后又变成空闲状态,这样就可以实现线程的重复利用

多线程与单线程的传输连接的不同点也在于连接的声明方式,即为每一个连接客户端建立一个线程,连接将使用Threading方法,被如下声明:
多线程声明

2.4 写一个简单的chat程序,并能互传文件,编程语言不限。

先放效果图(真的很傻,但是够应付实验了)
效果图

#!/usr/bin/env python
#coding:utf-8


import socket
import sys
import os

ip_port = ('127.0.0.1',9999)
sk = socket.socket()
sk.connect(ip_port)
base_path = 'E:\\Junior_1\计算机网络\lab2'
container = {'key':'','data':''}
while True:
    FLAG = input('0.收文件存到basepath下 1.传path目录下文件存到srv的basepath1下\n')
    sk.sendall(str(FLAG).encode('utf-8'))
    if FLAG=='1':
        # 客户端输入要上传文件的路径
        path = 'E:\\qq_file_receive\pic.gif'
        # 根据路径获取文件名
        file_name = os.path.basename(path)
        # print(file_name)
        # 获取文件大小
        file_size = os.stat(path).st_size
        # 发送文件名 和 文件大小
        Informf = (file_name + '|' + str(file_size))
        sk.send(Informf.encode())
        # 为了防止粘包,将文件名和大小发送过去之后,等待服务端收到,直到从服务端接受一个信号(说明服务端已经收到)
        message=sk.recv(1024)
        print(message.decode())
        send_size = 0
        f = open(path, 'rb')
        Flag = True
        while Flag:
            if send_size + 1024 > file_size:
                data = f.read(file_size - send_size)
                Flag = False
            else:
                data = f.read(1024)
                send_size += 1024
            sk.send(data)

        msg = sk.recv(1024)
        print(msg.decode())
        f.close()
    else :
        message=sk.recv(1024)
        print(message.decode(encoding='utf8'))

        message = input('请求文件名: ')
        message = str(message)
        # 发送数据 加码
        sk.sendall(message.encode('utf-8'))
        print('A等待.....')

        pre_data = sk.recv(1024).decode()
        # 获取请求方法、文件名、文件大小
        file_name, file_size = pre_data.split('|')
        # 防止粘包,给客户端发送一个信号。
        sk.sendall('get'.encode())
        # 已经接收文件的大小
        recv_size = 0
        # 上传文件路径拼接
        file_dir = os.path.join(base_path, message)
        f = open(file_dir, 'wb')
        Flag = True
        while Flag:
            # 未上传完毕,
            if int(file_size) > recv_size:
                # 最多接收1024,可能接收的小于1024
                data = sk.recv(1024)
                recv_size += len(data)
                # 写入文件
                f.write(data)
            # 上传完毕,则退出循环
            else:
                recv_size = 0
                Flag = False
        sk.sendall('下载完成'.encode())
        print('upload successed.')
        f.close()
sk.close()

#!/usr/bin/env python
#coding:utf-8

import socketserver
import os

class MyServer(socketserver.BaseRequestHandler):
    def handle(self):
        base_path = 'E:\\Junior_1\计算机网络'
        conn = self.request
        print ('connected...')
        while True:
            order = conn.recv(1024).decode(encoding='utf8')
            print(order)
            if order == '1':
                pre_data = conn.recv(1024).decode()
                # 获取请求方法、文件名、文件大小
                file_name, file_size = pre_data.split('|')
                # 防止粘包,给客户端发送一个信号。
                conn.sendall('收到'.encode())
                # 已经接收文件的大小
                recv_size = 0
                # 上传文件路径拼接
                file_dir = os.path.join(base_path, file_name)
                f = open(file_dir, 'wb')
                Flag = True
                while Flag:
                    # 未上传完毕,
                    if int(file_size) > recv_size:
                        # 最多接收1024,可能接收的小于1024
                        data = conn.recv(1024)
                        recv_size += len(data)
                        # 写入文件
                        f.write(data)
                    # 上传完毕,则退出循环
                    else:
                        recv_size = 0
                        Flag = False
                conn.sendall('下载完成'.encode())
                print('upload successed.')
                f.close()

            if order == '0':
                conn.sendall('B准备发送文件啦'.encode('utf-8'))
                path = conn.recv(1024).decode()
                file_name = os.path.join(base_path, path)
                print(file_name)
                # file_name = os.path.basename(path)
                # print(file_name)
                # 获取文件大小
                file_size = os.stat(file_name).st_size
                # 发送文件名 和 文件大小
                Informf = (file_name + '|' + str(file_size))
                conn.send(Informf.encode())
                # 为了防止粘包,将文件名和大小发送过去之后,等待服务端收到,直到从服务端接受一个信号(说明服务端已经收到)
                me=conn.recv(1024).decode()
                print(me)
                send_size = 0
                f = open(file_name, 'rb')
                Flag = True
                while Flag:
                    if send_size + 1024 > file_size:
                        data = f.read(file_size - send_size)
                        Flag = False
                    else:
                        data = f.read(1024)
                        send_size += 1024
                    conn.send(data)

                conn.recv(1024)
                f.close()


instance = socketserver.ThreadingTCPServer(('127.0.0.1',9999),MyServer)
instance.serve_forever()

#(服务端)

可能有线程安全问题,搞多线程又不标识线程号不保护,但是实验二应该也不会要求这么多把。
反正一个线程跑是莫得问题的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值