Python在线聊天室(windows)

Python在线聊天室(windows)


1、:准备系统参数配置模块 (settings.py)

#服务器地址
HOST = 'localhost'
#服务器端口
PORT = 9999
#服务器管道地址
PIPE_PORT=9998
#数据缓冲大小
BUFFERSIZE = 1024
#服务器端socket连接地址
ADDR = HOST,PORT
#服务端连接键盘和服务端的管道地址
PIPE_ADDR = HOST,PIPE_PORT
#默认语言选择
language = 'cn'

2、:国际化语言配置模块 (language.py)

language.py模块配置公共提示标准语言的国际化配置

from settings import language

if language == 'en':
    administrator='Administrator'
    adm_close_chatroom = 'Chatroom closed by Administrator'
    user_enter_chatroom='entered the chatroom'
    user_quit_chatroom='quited the chatroom'
    username='username>'
    user_already_exists='username already exists'
    connect_to='connected to'
    connect_from='connected from'
    please_input_username='please input your username'
    out_three_times='input repeat username three times'
    welcome='welcome new user'
elif language =='cn':
    administrator='管理员'
    adm_close_chatroom = '管理员关闭了聊天室'
    user_enter_chatroom='进入了聊天室'
    user_quit_chatroom='离开了聊天室'
    username='用户名>'
    user_already_exists='用户名已经存在'
    connect_to='连接到'
    connect_from='连接来自于'
    please_input_username='请输入用户名'
    out_three_times='输入用户名重复超过三次'
    welcome='欢迎新用户'

3、:准备聊天室公共模块 (common.py)

common.py模块提供两个方法,创建服务端socket和客户端socket

import os, sys
import socket
import shelve
import settings

#创建一个socket服务端
def createserver(addr):
    #print('crate server',addr)
    server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1)
    server.bind(addr)
    server.listen()
    return server
    
#创建一个socket客户端
def createclient(addr):
    #print('crate client',addr)
    client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    client.connect(addr)
    return client

4、:服务端模块 (server.py)

server.py模块创建服务端socket,供客户端进行连接,它主要处理聊天室管理员向所有在线连天用户发送广播信息,以及处理客户端在线用户发送的聊天内容信息转发功能

import os, sys
import socket
import select
import shelve
import settings
import language
import common
from multiprocessing import Process

#聊天室在线用户队列
users=[]
#服务端处理转发客户端聊天信息以及管理员键盘输入内容的方法
def accept(server,pipe_server):
    'accept 服务器接受函数'
    print('进入监听')
    # 使用select模块的select方法实现IO多路复用监听传输
    rlist = [server, pipe_server]
    wlist = []
    xlist = []
    while True:
        rs, ws, xs = select.select(rlist, wlist, xlist)
        for r in rs:    
            if r is server:
                print('服务器响应客户端连接信息=>',end='')
                conn,addr = server.accept()
                if(vlidate(conn)):
                    rlist.append(conn)
                    print(language.connect_from,addr)
                else:
                    conn.close()
            elif r is pipe_server:    ##服务器端输入内容
                print('服务器管道响应',end='(')
                conn,addr = pipe_server.accept()
                data = conn.recv(settings.BUFFERSIZE).decode()
                if data =='\n':
                    for c in rlist[2:]:
                        c.send(b'\n')
                        c.close()
                    server.close()
                    print(language.adm_close_chatroom,end="")
                    os._exit(0)
                else:
                    print(data.replace('\n',''),end=")\n")
                    data = language.administrator+":"+ data
                    for c in rlist[2:]:
                        c.send(data.encode())
            else:
                print("服务器响应客户端消息",end='(')
                data = r.recv(settings.BUFFERSIZE).decode()
                #print(data.find(language.user_quit_chatroom)>=0)
                if not data or data.find(language.user_quit_chatroom)>=0:
                    r.close()
                    rlist.remove(r)
                print(data,end=")\n")
                for c in rlist[2:]:
                    c.send(data.encode())
            
#校验登录用户的用户名是否已经存在于在线用户队列中                  
def vlidate(conn):
    username = conn.recv(settings.BUFFERSIZE).decode()
    print('登录用户名:',username,end="\n")
    if username in users:
        conn.send(language.user_already_exists.encode())
        return False
    else:
        users.append(username)
        conn.send((language.welcome+username).encode())
        return True

#主程序入口函数                
def main():
    #初始化服务器Socke
    server = common.createserver(settings.ADDR)

    #处理服务器键盘输入广播命令以及关闭聊天室命令
    pipe_server=common.createserver(settings.PIPE_ADDR)
    
    创建多线程,用来处理客户端发送信息的转发以及管理员向在线用户发送的广播信息
    p = Process(target=accept, args=(server, pipe_server))
    #p.daemon = True
    p.start()
    while True:
        try:
            data = sys.stdin.readline()
            #print(data)
        except KeyboardInterrupt:
            server.close()
            pipe_server.close()
            p.terminate()
            break
        if not data:
            continue
        elif data =='\n':
            #print('退出流程')
            pipe_client=common.createclient(settings.PIPE_ADDR)
            #print(pipe_client)
            pipe_client.send(b'\n')
            pipe_client.close()
            os._exit(0)
        else:
            pipe_client=common.createclient(settings.PIPE_ADDR)
            pipe_client.send(data.encode())
            pipe_client.close()
        
if __name__ =='__main__':
    users= []
    main()

5、:客户端模块 (client.py)

client.py模块创建客户端socket,并通过服务端地址连接服务端,它主要处理客户端登录,客户端向服务器端发送聊天信息以及接受服务端向自己发送的广播及其它在线用户发送的信息(由服务端转发)

import os, sys
import socket
import select
import settings
import language
import common
from multiprocessing import Process

#当前用户
curruser=''
#处理接收并打印服务端向自己发送的消息
def accept(client,curruser):
    rlist = [client]
    wlist = []
    elist = []
    while True:
        rs,ws,es = select.select(rlist,wlist,elist)
        for r in rs:
            if r is client:
                data = client.recv(settings.BUFFERSIZE)
                if data.decode() == '\n':
                    client.close()
                    print(language.adm_close_chatroom)
                    os.kill(os.getppid(), 9)
                    os._exit(0)
                    break
                else:
                    print(data.decode())
                    
#处理用户登录
def login():
    global curruser
    curruser = input(language.please_input_username)
    print(language.connect_to,settings.ADDR)

    client = common.createclient(settings.ADDR)
    client.send(curruser.encode())
    data  = client.recv(settings.BUFFERSIZE)
    if data.decode()==language.user_already_exists:
        print(language.user_already_exists)
        return (False)
    else:
        data = curruser+':'+language.user_enter_chatroom
        client.send(data.encode())
        return (True,client)
        
#主程序入口函数   
def main():
    #pipe_server = common.createserver(common.CLI_PIPE_ADDR)
    
    count = 0
    isLogin = False
    while isLogin==False and count<3:
        isLogin = login()
        count=count+1
    if len(isLogin)==2:
        client = isLogin[1]
        print(curruser)
        p = Process(target=accept,args=(client,curruser))
        p.daemon = True
        p.start()    

        while True:
            try:
            	 #处理客户端键盘输入并需要发送的消息
                data = sys.stdin.readline()
            except KeyboardInterrupt:
                # 如果遇到退出/中止信号,发送退出信息,关闭套接字,结束子进程,退出程序
                data = curruser+':'+user_quit_chatroom
                client.send(data.encode())
                client.close()
                pipe_client.close()
                p.terminate()
                break    
            if data=='\n':
                data = curruser+':'+language.user_quit_chatroom 
                client.send(data.encode())
                client.close()
                p.terminate()
                os._exit(0)
            else:
                data = curruser+':'+ (data.replace('\n',''))
                client.send(data.encode())
    else:
        print(language.out_three_times)
        
if __name__ == '__main__':
    main()    

6、:启动运行
6.1、键盘输入win+R,打开运行弹窗,输入cmd,然后回车,打开cmd命令窗口
在这里插入图片描述
6.2、使用cd命令进入到源文件所在位置,输入python server.py,运行服务端
在这里插入图片描述
6.3、当命令窗口出现:进入监听,说明服务端成功启动
在这里插入图片描述
6.4、重复6.1,6.2操作重新打开一个cmd命令窗口,输入python client.py命令来启动客户端
在这里插入图片描述
6.5、按照提示输入登录用户名,此处输入teamo,并按回车键
客户端显示
在这里插入图片描述
服务端显示
在这里插入图片描述

7、完整功能展示
可以在多打开一个客户端,登录进聊天室,这样更清楚聊天室的整个运行处理过程,如下面截图所示
在这里插入图片描述
管理员可以给所有在线用户发送广播信息,也可以不输入任何信息直接回车(关闭整个聊天室),客户端也可以不输入任何信息直接回车(退出聊天室)
在这里插入图片描述
到此,整个聊天室功能介绍完毕,当然目前只做了公开聊天,并没有做一对一的私聊,并且可以使用python的GUI去实现带窗体的聊天室,有兴趣的同学可以自己尝试

猜你喜欢

转载自blog.csdn.net/teamo_m/article/details/120529334