[python] Python development of chat room based on Socket

(Follow "Test Development Automation" Gong Zhonghao for more learning content)

1. Brief introduction of Socket

SOCKET is a convention or a way of communicating between computers. Through the socket agreement, a computer can receive data from other computers, and can also send data to other computers.

The main working modes of Socket are as follows:
insert image description here

We use the above mode to develop a chat room tool. The main development module includes two parts:

  1. client development
  2. server development

It can be deployed on the same computer. Since I only have one computer, I deployed both the server and the client on my own computer. You can also deploy it on different computers in the same LAN, or use other different servers for deployment. The effect is shown below:
Please add a picture description

If your company's network does not allow access to the Internet, then you can secretly make a small chat software in the LAN for chatting between you and your beloved girl. Ha ha ha ha. .

2. Create a server server

The process of creating a server can be roughly divided into the following steps:
1) Create a client socket (socket) object
2) Bind the IP address and port number
3) Set up monitoring
4) Wait for the connection request from the client
5) Accept data
6) Send data
7) Close the client socket (socket)

2.1 Create server initialization

This part is mainly used to initialize the server and create a Severt class that continuously monitors the requests sent by the client.

class Server:
    def __init__(self):
        self.server = socket.socket()    # 创建客户端套接字(socket)对象
        self.server.bind(("192.168.20.164", 8989))  # 绑定IP地址和端口号
        self.server.listen(15)     # 设置监听 15表示服务端等待排队连接的最大数量
        self.clients = []          # 用于存放客户端的响应信息
        self.clients_name_ip = {
    
    }  # 用与存放客户端名称与IP
        self.get_conn()            # 监听客户端连接

2.2 Listening for client connections

By setting an infinite loop, our server is constantly listening to the client's connection request. Once the client initiates a connection request, the accept() method returns the socket connection object and IP address of the currently connected client.
Through print(cilent), you can see:

<socket.socket fd=460, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('192.168.20.164', 8989), raddr=('192.168.20.164', 59239)>

At this time, the server will input a piece of information data to the client, and the server needs to encode the information and send it to the client. At the same time, after the client receives the information, it needs to convert its section code into content that we can recognize.

def get_conn(self):
    while True:
        client, address = self.server.accept()    # 等待接收连接请求
        print("IP为{}的使用者正在请求连接。".format(address))
        data = "与服务器链接成功,请输入昵称才可以聊天"
        client.send(data.encode())   # server与client通信,send() decode
        self.clients.append(client)  # 链接用户添加到服务器的用户列表
        Thread(target=self.get_msg, args=(client, self.clients,self.clients_name_ip, address)).start()

2.3 Processing client messages

In order to bind the sent name with the IP, it is necessary to decode the content of the username sent by the client and add it to the clients_name_ip parameter. At this point, once the client sends a connection request and enters a nickname, the nickname will be decoded and stored in the name variable.

At this point, the server starts to listen to the client's messages in a loop. And continue to decode the messages sent by the client. And the message is re-encoded and sent to all clients through a for loop.

In addition, if it is detected that the message sent by the client is a "Q" character, then the client will be closed.

def get_msg(self, client, clients, clients_name_ip, address):
    name = client.recv(1024).decode()  # 接受客户端发来的昵称
    print("昵称:【{}】 设置成功".format(name))
    clients_name_ip[address] = name    # 昵称与IP进行绑定
    while True:                        # 循环监听客户端消息
        try:
            recv_data = client.recv(1024).decode()
        except Exception as e:
            self.close_client(client, address)
            break
        # 入=如果用户输入Q,推出
        if recv_data.upper() == "Q":
            self.close_client(client, address)
            break
        for c in clients:
            c.send((clients_name_ip[address] + " " + time.strftime("%x")+"\n"+recv_data).encode())

Three, create a client Client

The process of creating a client can be roughly divided into the following steps:
1) Create a client socket (socket) object
2) Establish a connection with a server-side socket (socket)
3) Send data
4) Accept data
5) Close the client socket

3.1 Create server initialization

The client uses PyQT5, and the client is made into an interface for interaction. I won't explain too much about PyQT5 here. The PyQT5 used here is relatively simple, focusing on the server-side socket development.

First, create a client socket object, connect to the server port, and start a worker thread.

class Client(QWidget):
    def __init__(self):
        super(Client, self).__init__()
        self.setGeometry(600, 300, 360, 300)
        self.setWindowTitle("聊天室")
        self.add_ui()   # 界面UI,这个跟socket无关
        
        self.client = socket.socket()  # 与服务器链接
        self.client.connect(("127.0.0.1", 8989))
        self.work_thread()        # 调用线程

3.2 Send message

To send a message, the user clicks the send button. After clicking the send button, QT will trigger the execution of the send_msg function in the form of a signal. At this point, the message will be decoded and sent to the server. If it is detected that the sent message is the character 'Q', the client will be exited.

def btn_send(self):   # 发送按钮点击,信号发射
    self.button.clicked.connect(self.send_msg)
def send_msg(self):   # 检测到发送按钮点击,该客户端就会向服务端发送数据
    msg = self.message.text()
    self.client.send(msg.encode())
    if msg.upper() == "Q":
        self.client.close()
        self.destroy()
    self.message.clear()

3.3 Receive messages

By receiving the message, the received message is decoded, and appended to the QT control in the form of append for display in the interface

def recv_msg(self):
    while True:
        try:
            data = self.client.recv(1024).decode()
            print(data)
            data = data + "\n"
            self.content.append(data)
        except:
            exit()

3.3 Thread work

By calling this method, start the sending message thread and receiving message thread.


def work_thread(self):
    Thread(target=self.btn_send).start()   # 发送消息
    Thread(target=self.recv_msg).start()  

3.4 Thread work

Step 1: Start the server
Step 2: Start a Client (pycharm)
Step 3: Start another Client (cmd)

insert image description here

Isn't it fun? It can also be used as a course design! If you need the source code, you can follow me Gong Zhonghao to view historical articles.

(Follow "Test Development Automation" Gong Zhonghao for more learning content)

insert image description here

Guess you like

Origin blog.csdn.net/weixin_44244190/article/details/129048310