白冥 发表于 2024-4-28 00:50:29

基于python的多线程聊天室的客户端部分(包括ini配置文件)

本帖最后由 白冥 于 2024-4-29 00:20 编辑

事先说明,代码有点长,可能被吞:

client.py
from client_socket import ClientSocket
from client_thread import ClientThread
class client:
    def __init__(self):
      self.socket=ClientSocket()
      self.thread=ClientThread(self.socket)
      self.socket.start()
      self.thread.start_thread(
            send_thread=self.socket.send,
            receive_thread=self.socket.receive,
            heartbeat_thread=self.socket.heartbeat
      )
      if not self.thread.condition:
            self.socket.stop()
client_socket.py
import socketimport timefrom config import Configfrom message import Messageclass ClientSocket:    def __init__(self):      self._init_socket()      self.id=Config.clientHost      self.running=True      self.server_disconnected=False    def _init_socket(self):      self.socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)      self.socket.connect((Config.serverHost,Config.usingPort))    def start(self):      self.send(Config.MessageType.inquire,Config.Instruction.please,self.id,Config.serverId)    def stop(self):      self.running=False      self.socket.close()    def send(self,type,instruction,sender,addressee,content=''):      MESSAGE=Message.dumps(type,instruction,sender,addressee,content)      self.socket.sendall(MESSAGE)      self.handle_send(MESSAGE)    def receive(self):      MESSAGE=self.socket.recv(Config.maximumTextLimit).decode()      self.handle_receive(MESSAGE) if Message.is_message(MESSAGE) else None    def handle_send(self,message):      match message['type']:            case Config.MessageType.inquire:                match message["instruction"]:                  case Config.Instruction.bye:                        self.stop()    def handle_receive(self,message):      DICTIONARY=Message.loads(message)      if type(DICTIONARY)==dict:            match DICTIONARY['type']:                case Config.MessageType.transmit:                  match DICTIONARY['instruction']:                        case Config.Instruction.text:                            print(f'A message from {DICTIONARY['sender']}\n')                            print('Main body:\n')                            print(f'{DICTIONARY['content']}\n')                case Config.MessageType.detection:                  match DICTIONARY['instruction']:                        case Config.Instruction.detect:                            match DICTIONARY['sender']:                              case Config.serverId:                                    self.server_disconnected=False                case Config.MessageType.inquire:                  match DICTIONARY['instruction']:                        case Config.Instruction.bye:                            print(f'Addressee {DICTIONARY['sender']} stopped communication')                case Config.MessageType.respond:                  match DICTIONARY['instruction']:                        case Config.Instruction.text:                            print(f'A message from {DICTIONARY['sender']}\n')                            print('Main body:\n')                            print(f'{DICTIONARY['content']}\n')                case Config.MessageType.report:                  match DICTIONARY['sender']:                        case Config.serverId:                            match DICTIONARY['instruction']:                              case Config.Instruction.id:                                    print(f'You has been assigned an ID:{DICTIONARY['content']}')                                    self.sender_id=DICTIONARY['content']                              case Config.Instruction.known:                                    print('Reconnecting to the server succeeded.')    def heartbeat(self):      self.send(Config.MessageType.detection,Config.Instruction.detect,self.id,Config.serverId)      self.server_disconnected=True      time.sleep(Config.heartbeatRate)      if self.server_disconnected:            print('We temporarily lost contact with the server.')            if not self.reconnect():                self.stop    def reconnect(self,attempt=1):      if attempt<=Config.maximumAttemptLimit:            try:                self.stop()                self.running=True                self._init_socket()                return True            except Exception as error:                print(f'Failed to reconnect to the server')                time.sleep(5)                self.reconnect(attempt+1)      else:            return False
client_thread.py
import threadingclass ClientThread:    def __init__(self,client_socket):      self.condition=client_socket.running    def loop(self,callback):      while self.condition:            callback()    def start_thread(self,**threads):      try:            threads_list:list=[]            for thread,callback in threads.items():                thread=threading.Thread(target=ClientThread.loop,args=(self,callback))                thread.start()                threads_list.append(thread)            for thread in threads_list:                thread.join()      except Exception as error:            print(f'An error occurs:{error}')            self.condition=False
config.py
import configparserCONFIG=configparser.ConfigParser()CONFIG.read('config.ini')class Config:    serverHost=CONFIG.get('SERVER','host')    clientHost=CONFIG.get('CLIENT','host')    usingPort=CONFIG.getint('SERVER','port')    serverId=CONFIG.get('SERVER','id')    heartbeatRate=CONFIG.getint('CLIENT','heartbeat_rate')    maximumAttemptLimit=CONFIG.getint('CLIENT','maximun_attempt_limit')    maximumTextLimit=CONFIG.getint('TEXT','maximum_text_limit')    class Instruction:      text=CONFIG.get('INSTRUCTIONS','send_text')      file=CONFIG.get('INSTRUCTIONS','send_file')      error=CONFIG.get('INSTRUCTIONS','send_error')      bye=CONFIG.get('INSTRUCTIONS','end_communication')      please=CONFIG.get('INSTRUCTIONS','request_to_join')      id=CONFIG.get('INSTRUCTIONS','allocation_id')      call=CONFIG.get('INSTRUCTIONS','request_reconnection')      known=CONFIG.get('INSTRUCTIONS','successfull_reconnection')      detect=CONFIG.get('INSTRUCTIONS','heartbeat_detection')    class MessageType:      transmit=CONFIG.get('MESSAGE_TYPES','transmit')      detection=CONFIG.get('MESSAGE_TYPES','detection')      inquire=CONFIG.get('MESSAGE_TYPES','inquire')      respond=CONFIG.get('MESSAGE_TYPES','respond')      report=CONFIG.get('MESSAGE_TYPES','report')
message.py
import jsonclass Message:    @staticmethod    def dumps(msg_type,instruction,sender,addressee,content):      DICTIONARY={            "type":msg_type,            "instruction":instruction,            "sender":sender,            "addressee":addressee,            "content":content,      }      return json.dumps(DICTIONARY).encode()    @staticmethod    def is_message(message):      TEMPLATE={"type","instruction","sender","addressee","content"}      try:            DICTIONARY=json.loads(message)            if type(DICTIONARY)==dict:                return set(DICTIONARY.keys())==TEMPLATE      except json.JSONDecodeError:            return False    @staticmethod    def loads(message):      if Message.is_message(message):            return json.loads(message)

config.ini

host=127.0.0.1
port=6363
id=Server

host=localhost
heartbeat_rate=10
maximum_attempt_limit=3

send_text=/text
send_file=/file
send_error=/error
end_communication=/bye
request_to_join=/please
allocation_id=/id
request_reconnection=/call
successfull_reconnection=/known
heartbeat_detection=/detect

transmit=transmit
detection=detection
inquire=inquire
respond=respond
report=report

maximum_text_limit=4096



娱乐法师火布偶 发表于 2024-4-28 00:53:38

看起来应该是python3的代码,不过python3的版本也是挺多的

凯诺斯 发表于 2024-4-28 00:59:26

好专业的感觉呀,多线程聊天室是用于聊天用的代码吗?

JYYYY 发表于 2024-4-28 01:01:09

泥潭要转型github了吗

Riverlethe 发表于 2024-4-28 01:07:43

已晕,外行看热闹,内行看门道吧……

thh866 发表于 2024-4-28 01:18:28

专业起来了,,,话说服务端咋没一起放上来

轮回2L 发表于 2024-4-28 01:39:58

好专业的样子,只能看看热闹的说XD

毛茸茸兽兽 发表于 2024-4-28 01:56:30

喔⊙ω⊙搜了搜,类似这种的咩https://blog.csdn.net/weixin_62428212/article/details/135996783

前方无怪 发表于 2024-4-28 02:18:34

看起来好复杂的样子诶
咱对于代码一窍不通hh坐等一个傻瓜式教学QAQ

ditto 发表于 2024-4-28 04:15:26

感觉是个很实用的工具,可惜我不懂惹~

黑达克 发表于 2024-4-28 04:33:35

好复杂的代码,像我这种咸鱼就只能围观大佬们交流了{:6_194:}

不是卖萌的基佬 发表于 2024-4-28 06:57:08

{:6_164:}虽然标题已经说明是什么东西,但我还是看不懂啊…

Burry 发表于 2024-4-28 06:57:13

挺复杂的代码,感觉要同行才看得懂呢。

koh 发表于 2024-4-28 07:39:38

好好学习,以后说不定泥潭靠你出力~

you9632587 发表于 2024-4-28 08:12:27

看上去好专业的东西,泥潭真是各种大佬都有啊

山涧轶闻 发表于 2024-4-28 08:44:19

{:6_188:}有种在泥潭看到了课程设计精简版的美

墨燝 发表于 2024-4-28 15:55:52

懂了,下次写什么小玩意要嵌聊天的时候可以参考了
作为简易的就是足够简易才好,这个就很不错

rockdjs 发表于 2024-4-28 17:23:09

额,我觉得是不是应该写个说明什么的?

cdcai 发表于 2024-4-28 20:33:45

没有介绍看不懂是做什么的{:6_167:}

大臣 发表于 2024-4-28 21:04:27

Python的代码真简洁,就这么短一点,要是用其他语言来写估计要写一大堆。
页: [1] 2
查看完整版本: 基于python的多线程聊天室的客户端部分(包括ini配置文件)