本文编写于 226 天前,最后修改于 226 天前,其中某些信息可能已经过时。
前言
我又双叒叕好久不更新了,来记录下最近的学习成果叭,最近学习了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
就是这个样子啦,有啥写的比较烂的地方欢迎大佬指正,初学者有啥不懂的也欢迎提问吖!