Python online chat room (windows)

Python online chat room (windows)


1. Prepare the system parameter configuration module (settings.py)

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

2.: Internationalization language configuration module (language.py)

The language.py module configures the internationalization configuration of the public prompt standard language

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. Prepare the chat room common module (common.py)

The common.py module provides two methods, creating a server socket and a client 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 module (server.py)

The server.py module creates a server socket for the client to connect. It mainly handles the chat room administrator sending broadcast information to all online users, and handles the chat content information forwarding function sent by the online user of the client.

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 module (client.py)

The client.py module creates a client socket and connects to the server through the server address. It mainly handles client login, the client sends chat information to the server, and accepts broadcasts sent by the server to itself and information sent by other online users ( forwarded by the server)

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. Start and run
6.1, enter win+R on the keyboard, open the running pop-up window, enter cmd, and press Enter to open the cmd command window
insert image description here
6.2, use the cd command to enter the location of the source file, enter python server.py, and run the server
insert image description here
6.3. When the command window appears: enter the monitoring, it means that the server has successfully started
insert image description here
6.4, repeat 6.1, 6.2 to reopen a cmd command window, enter the python client.py command to start the client
insert image description here
6.5, follow the prompts to enter the login user name, here Enter teamo and press the Enter key
The client displays
insert image description here
The server displays
insert image description here

7. Complete function display
You can open one more client and log in to the chat room, so that you can understand the entire operation and processing process of the chat room more clearly. As shown in the screenshot below, the
insert image description here
administrator can send broadcast information to all online users, or you can not enter any Enter the information directly (close the entire chat room), and the client can also press Enter without entering any information (exit the chat room).
insert image description here
Here, the introduction of the entire chat room function is completed. Of course, only public chats have been done at present, and there is no pairing One's private chat, and you can use the python GUI to implement a chat room with a form. Interested students can try it by themselves

Guess you like

Origin blog.csdn.net/teamo_m/article/details/120529334