本文编写于 116 天前,最后修改于 116 天前,其中某些信息可能已经过时。

前言

        我又双叒叕好久不更新了,来记录下最近的学习成果叭,最近学习了Python的多线程和socket,然后突发奇想结合起来写了一个小玩意,这个小玩意呢可以实现实时通信,分别是通过一个服务端和多个客户端,客户端将消息发送到服务端,服务端再将消息转发给你想要发送给的那个人,并且支持一些指令如查看当前在线名单,查看某用户信息等。

效果



源码

# Server.py

import socket
import threading
import json

serverAddress = ("0.0.0.0", 9000)

jsonDicts = {
    'dictType': 0,
}

onlineList = []
userData = {}
threadDicts = {}


def jsonEncode(dicts):
    return json.dumps(dicts).encode('utf-8')


def jsonDecode(dicts):
    return json.loads(dicts.decode('utf-8'))


class DataBind:
    def __init__(self, threadName):
        self.threadName = threadName

    def bind(self, dicts, connect, address):
        onlineList.append(dicts["username"])
        userData[dicts["username"]] = self.threadName
        threadDicts[self.threadName] = {
            'username': dicts["username"],
            'phoneNumber': dicts["phoneNumber"],
            'connect': connect,
            'address': address,
            'ip': address[0],
            'port': address[1]
        }
        print("user " + dicts["username"] + " connect successful...")
        print("user " + dicts["username"] + " data binding successful...")
        return True

    def unBind(self):
        userInfo = threadDicts[self.threadName]
        onlineList.pop(onlineList.index(userInfo["username"]))
        userData.pop(userInfo["username"])
        threadDicts.pop(self.threadName)
        print("user " + userInfo["username"] + " disconnect...")
        print("user " + userInfo["username"] + " data unbind successful...")
        return True


class UserCommand:
    def __init__(self):
        ...

    def help(self, args):
        str = """
        ---------- Command Help ----------
            /getOnlineUser:/ls  view online users...
            /see [UserName]  view user info...
            /help  view help...
        ----------   Help End   ----------
        """
        return str

    def getOnlineUser(self, args):
        return str(onlineList)

    def ls(self, args):
        return self.getOnlineUser(args)

    def see(self, args):
        arg = args.split(" ")
        if arg[0] in onlineList:
            userDict = threadDicts[userData[arg[0]]]
            str = """
            ---------- User Info ----------
                 UserName: %s
                UserPhone: %s
                   UserIP: %s
            ---------- Info  End ----------
            """ % (userDict["username"], userDict["phoneNumber"], userDict["ip"])
            return str
        else:
            return "The user is not online..."


class SocketServer(socket.socket):

    def __init__(self):
        super(SocketServer, self).__init__()

    def bind(self, address):
        print("Binding address '" + str(address) + "'...")
        super(SocketServer, self).bind(address)

    def accept(self):
        connect, address = super(SocketServer, self).accept()
        print(str(address) + " connect this server...")
        return connect, address


class SocketThread(threading.Thread):
    def __init__(self, connect, address):
        super(SocketThread, self).__init__()
        self.connect = connect
        self.address = address

    def run(self):
        while True:
            dataBind = DataBind(self.getName())
            try:
                msg = jsonDecode(self.connect.recv(1024))
                if msg["dictType"] == 0:
                    dataBind.bind(msg, self.connect, self.address)
                    jsonDicts["dictType"] = 1
                    jsonDicts["sender"] = "Server"
                    str = """
                        user data binding successful...
                        
                        Input /help view help...
                        Input >[UserName] [Message] send message
                    """
                    jsonDicts["message"] = str
                    self.connect.send(jsonEncode(jsonDicts))
                elif msg["dictType"] == 1:
                    if msg["toUser"] in onlineList:
                        userDict = threadDicts[userData[msg["toUser"]]]

                        jsonDicts["dictType"] = 0
                        jsonDicts["sender"] = msg["username"]
                        jsonDicts["message"] = msg["message"]

                        userDict["connect"].send(jsonEncode(jsonDicts))
                    else:
                        jsonDicts["dictType"] = 1
                        jsonDicts["sender"] = "Server"
                        jsonDicts["message"] = "The user is not online..."
                        self.connect.send(jsonEncode(jsonDicts))
                elif msg["dictType"] == 2:
                    if hasattr(UserCommand(), msg["userCommand"]):
                        command = getattr(UserCommand(), msg["userCommand"])
                        jsonDicts["dictType"] = 1
                        jsonDicts["sender"] = "Server"
                        jsonDicts["message"] = command(msg["userArgs"])
                        self.connect.send(jsonEncode(jsonDicts))
            except socket.error as e:
                dataBind.unBind()
                return False


if __name__ == "__main__":
    sock = SocketServer()
    sock.bind(serverAddress)
    sock.listen()

    while True:
        connect, address = sock.accept()

        thread = SocketThread(connect, address)
        thread.start()
# Client.py

import socket
import threading
import json

connectAddress = ("127.0.0.1", 9000)

jsonDicts = {
    'dictType': 0,
    'username': 'ZeroY',
    'phoneNumber': 17700000000
}


def jsonEncode(dicts):
    return json.dumps(dicts).encode('utf-8')


def jsonDecode(dicts):
    return json.loads(dicts.decode('utf-8'))


class SocketClient(socket.socket):
    def __init__(self):
        super(SocketClient, self).__init__()

    def connect(self, address):
        super(SocketClient, self).connect(address)
        self.send(jsonDicts)
        print("Connect to " + str(address))

    def send(self, data: bytes, flags: int = ...):
        super(SocketClient, self).send(jsonEncode(data))


class SocketThread(threading.Thread):
    def __init__(self, sockets):
        super(SocketThread, self).__init__()
        self.sockets = sockets

    def run(self):
        while True:
            userMessage = input("you command: ")
            if userMessage.strip() == "": continue
            if userMessage[0] == '>':  # send info to user
                jsonDicts["dictType"] = 1
                commandArgs = userMessage.split(" ")
                if '>' in commandArgs[0]:
                    jsonDicts["toUser"] = commandArgs[0].lstrip(">")
                    jsonDicts["message"] = userMessage.lstrip(commandArgs[0] + " ")
            elif userMessage[0] == '/':  # send command to server
                jsonDicts["dictType"] = 2
                commandArgs = userMessage.split(" ")
                if '/' in commandArgs[0]:
                    jsonDicts["userCommand"] = commandArgs[0].lstrip("/")
                    jsonDicts["userArgs"] = userMessage.lstrip(commandArgs[0] + " ")
            else:
                continue
            self.sockets.send(jsonDicts)


if __name__ == "__main__":
    sock = SocketClient()
    sock.connect(connectAddress)

    thread = SocketThread(sock)
    thread.start()

    while True:
        try:
            msg = jsonDecode(sock.recv(1024))
            print("\n" + msg["sender"] + " to you: " + msg["message"])
        except socket.error as e:
            print("The server closed connect...")
            sock.close()
            break

就是这个样子啦,有啥写的比较烂的地方欢迎大佬指正,初学者有啥不懂的也欢迎提问吖!