20214321吴萌源 《Python程序设计》实验四报告

20214321 2022-2022-4 《Python程序设计》实验四报告

课程:《Python程序设计》
班级: 2143
姓名: 吴萌源
学号:20214321
实验教师:王志强
实验日期:2022年5月4日
必修/选修: 公选课

1.实验内容

     在python中用socket和多线程编程写了一个多人在线聊天器,客户端和服务端通过socket套接字(TCP)进行通信,在客户端中可以把聊天消息记录下来,用户可以打开自行回顾。

2.实验过程

(1)服务端

服务端的基本配置先写好

 

在服务端中要实例每一个与客户端连接的socket对象,并用列表储存每个socket。加入循环,在循环中服务端会不断与接入的客户端建立连接并开启线程与其通信。

 

在线程中,接收到的消息会通过字符串分割,获取客户端昵称和消息,获取客户端昵称一是为了分辨出管理员,同时管理员可以对服务器进行关闭处理;二是可以让每个用户分辨出是谁发来的消息。

 

做好分辨操作后,把用户昵称与信息拼接,通过for循环遍历列表把消息发送到每一个socket对象中。

 

(2)客户端

客户端中也要配置信息

 

客户端中也会有一个线程,在该线程有循环不断接受服务器消息。

 

客户端接入服务端后输入中间的昵称便可以开始进行聊天。

 

同时客户端有文件操作会对聊天消息进行写入保存,以供用户回顾。

 

 源码:

 1 from socket import *
 2 from threading import Thread
 3 
 4 # 配置信息
 5 IP = '127.0.0.1'  # 地址
 6 PORT = 50000  # 端口号
 7 BUF_LEN = 512  # 一次从socket缓冲区输入的字节数据大小
 8 MASTER_NAME = '1001'
 9 MASTER_COMMAND = '202143xxEXIT'
10 DECOLLATOR = '|'
11 OPENSIGN = True
12 
13 # socket
14 listenSocket = socket(AF_INET, SOCK_STREAM)  # 实例一个socket对象
15 listenSocket.bind((IP, PORT))  # socket绑定地址与端口
16 listenSocket.listen(20)  # 最多20个用户
17 print(f'服务端启动成功在{PORT}端口等待客户端链接……')
18 
19 
20 # 这是新线程执行的函数,每个线程负责和一个客户端进行通信
21 def client_handler(data_Socket, add_r):
22     while True:
23         recv_ed = data_Socket.recv(BUF_LEN)
24         # 当对方关闭连接的时候,返回空字符串
25         if not recv_ed:
26             for i in USER:
27                 if i == data_Socket:
28                     del i
29             print(f'客户端{add_r} 关闭了连接')
30             break
31 
32         # 读取的字节数据是bytes类型,需要解码为字符串,分割字符串获取信息
33         u_nick = recv_ed.decode().split(DECOLLATOR)[0]
34         # 未获取到昵称处理
35         if u_nick == '':
36             u_nick = '懒得输入昵称的帅哥或美女'
37 
38         # 消息拼接
39         msg = recv_ed.decode().split(DECOLLATOR)[1]
40         info = u_nick+':'+msg
41         print(f'收到{add_r}信息: {info}')
42 
43         # 管理员关闭服务器处理
44         if info == MASTER_NAME+':'+MASTER_COMMAND:
45             for i in USER:
46                 i.send('服务器已关闭'.encode())
47             listenSocket.close()
48             break
49 
50         # 遍历所有客户端,把消息发到各个客户端
51         for i in USER:
52             i.send(f'{info}'.encode())
53     data_Socket.close()
54     for i in USER:
55         i.close()
56 
57 
58 # 建立列表,收集客户端socket
59 USER = []
60 
61 while True:
62     # 在循环中,一直接受新的连接请求
63     dataSocket, addr = listenSocket.accept()  # 建立与客户端的通信
64     USER.append(dataSocket)
65     addr = str(addr)
66     print(f'一个客户端{addr}链接成功')
67 
68     # 创建线程处理与这个客户端的消息收发
69     th = Thread(target=client_handler, args=(dataSocket, addr))
70     th.start()
服务端
 1 from socket import *
 2 from threading import Thread
 3 from time import localtime, strftime, time
 4 
 5 # 配置信息
 6 IP = '127.0.0.1'
 7 SERVER_PORT = 50000
 8 BUF_LEN = 512
 9 DECOLLATOR = '|'
10 
11 # socket
12 dataSocket = socket(AF_INET, SOCK_STREAM)
13 dataSocket.connect((IP, SERVER_PORT))
14 
15 
16 # 这是新线程执行的函数,用来接收服务器消息
17 def receive_handler(data_Socket, ):
18     while True:
19         receive = data_Socket.recv(BUF_LEN)
20         print(receive.decode())
21         if not receive:
22             break
23         # 写入其他用户聊天内容
24         get_time = strftime('%H:%M:%S', localtime(time()))
25         file1.write(str(get_time))
26         file1.write('\n')
27         file1.write(receive.decode())
28         file1.write('\n')
29     data_Socket.close()
30     dataSocket.close()
31     exit()
32 
33 
34 # 打开文件夹,计入聊天器使用时间
35 file1 = open("test", "a+", encoding="GBK")
36 Open_time = strftime('%H:%M:%S', localtime(time()))
37 file1.write('启动时间:'+str(Open_time))  # 写入打开时间,记录在什么时间段聊天
38 file1.write('\n')
39 
40 # 建立线程与接收服务器消息
41 th = Thread(target=receive_handler, args=(dataSocket, ))
42 th.start()
43 
44 # 输入昵称
45 nickname = input('请输入您的昵称:')
46 print('可以开始聊天了')
47 
48 # 循坏:不断向服务器发送消息
49 while True:
50 
51     toSend = input()
52     now_time = strftime('%H:%M:%S', localtime(time()))
53     file1.write(str(now_time))
54     file1.write('\n')
55     file1.write(toSend)
56     file1.write('\n')
57     if toSend == '':
58         now_time = strftime('%H:%M:%S', localtime(time()))
59         file1.write('您已关闭聊天室,关闭时间:'+str(now_time))
60         file1.write('\n')
61         break
62     dataSocket.send((nickname+DECOLLATOR+toSend).encode())
63 
64 dataSocket.close()
65 file1.close()
客户端

 运行:

程序在pycharm和华为ESC服务器上运行结果在视频中展现,这里就不再进行展示。

 

3.全课总结

   在这学期的python课上学到的东西很多,王老师是python语言的一个门童,把我们领入python的修行当中。

   师傅领进门,修行在自身。这句话是我在python课上的感受之一,王老师讲课讲的很快,一节课将的东西对我这样的初学者感觉很多,加上我们一周才上一次课,下课如果没有复习很容易就忘了上节课讲的内容。我感觉我们这门课虽然简单,但是学的东西很多,覆盖的也有些广,需要上网查很多东西,也要上网自学很多内容。

   本课另一个感受就是实践是检验真理的唯一标准。python课上接触的内容在以前没接触过,在进行一些实验的时候总是畏首畏尾的,不敢做好像怕把什么东西弄坏一样。在进行了几次实验后,我明白了做实验就是得“整”,不要怕把代码整坏,有问题去问、去查,没什么是解决不了的。

   总结一下本课就是收获满满,同时也放开了胆,敢做些东西。

 

4.参考资料

1.  Python3 多线程|菜鸟教程

2. 【python项目实战】创作自己的多人聊天室

posted @ 2022-05-31 19:44  babobi  阅读(46)  评论(0编辑  收藏  举报