def publishAtQos2(sock, topic, message, retain): """ Description: 发送一则服务质量等级为2的消息。 Args: sock(Socket): 客户端socket对象。 topic(string): 消息主题。 message(string): 消息内容。 retain(int): 消息保留标志。 Returns: packetIdentifier(int) 本次请求使用的报文标识符。 Raises: IOException socket连接异常。 """ packetIdentifier = generatePacketIdentifier() sendMessage( sock, encoders.PUBLISH_Encoder(0, 2, retain, topic, packetIdentifier, message)) tmpPublishAtQos2.append({ "packetIdentifier": packetIdentifier, "waitingFor": 'PUBREC' }) return packetIdentifier
def publishAtQos0(sock, topic, message, retain): """ Description: 发送一则服务质量等级为0的消息。 Args: sock(Socket): 客户端socket对象。 topic(string): 消息主题。 message(string): 消息内容。 retain(int): 消息保留标志。 Returns: None Raises: IOException socket连接异常。 """ sendMessage(sock, encoders.PUBLISH_Encoder(0, 0, retain, topic, 0, message)) print("[" + getTime() + "]" + " [CLIENT/INFO] Message published at Qos0" + ".")
def decode(self, data): """ Description: 对于给定的报文字节串进行解码,并实现对应的逻辑响应。 Args: data(byte[]) 待解码的报文字节串。 Returns: None Raises: decoders.IllegalMessageException 消息解码错误。 IOException socket连接错误。 """ if data == b'': return try: messageType, results = decoders.message_Decoder(data) if messageType == definition.messageType.CONNECT: if results['clientId'].isalnum( ) and results['clientId'].__len__( ) >= 1 and results['clientId'].__len__() <= 23: self.clientId = results['clientId'] if checkUser(results['userName'], results['password']) == 2: if results['cleanSession'] == 1: removeSubscribe(results['clientId']) self.keepAlive = results['keepAlive'] self.willFlag = results['willFlag'] if self.willFlag == 1: self.willTopic = results['willTopic'] self.willMessage = results['willMessage'] self.willQos = results['willQos'] self.willRetain = results['willRetain'] print("[" + getTime() + "]" + " [SERVER/INFO] Client " + str(self.address) + " has connected.") sessionPresent = getSubscribe(self.clientId).__len__() if sessionPresent > 0: sessionPresent = 1 self.send( encoders.CONNACK_Encoder( sessionPresent, definition.ConnackReturnCode.ACCEPTED)) scs = getSubscribe(self.clientId) for sc in scs: for retainedMessage in retainedMessages: if checkFatherSon( sc[1], retainedMessage['topic'] ) or retainedMessage['topic'] == sc[1]: packetIdentifier = generatePacketIdentifier( ) print(111) self.send( encoders.PUBLISH_Encoder( 0, sc[2], 0, retainedMessage['topic'], packetIdentifier, retainedMessage['message'])) if sc[2] == 2: timer = threading.Timer( ACK_TIMEOUT, pubrecNotReceived, [ self, ]) timeoutTimers.append({ 'clientId': self.getClientId(), 'packetIdentifier': packetIdentifier, 'waitingFor': 'PUBREC', 'timer': timer }) timer.start() elif sc[2] == 1: timer = threading.Timer( ACK_TIMEOUT, pubackNotReceived, [ self, ]) timeoutTimers.append({ 'clientId': self.getClientId(), 'packetIdentifier': packetIdentifier, 'waitingFor': 'PUBACK', 'timer': timer }) timer.start() print( "[" + getTime() + "]" + " [SERVER/INFO] A retained message sent to Client " + str(self.address) + " at packet " + str(packetIdentifier) + " .") retainedMessages.remove(retainedMessage) break keepAliveThread = threading.Thread(target=self.counter) keepAliveThread.start() elif checkUser(results['userName'], results['password']) == 0: self.send( encoders.CONNACK_Encoder( 0, definition.ConnackReturnCode. REFUSED_INVALID_USER)) print("[" + getTime() + "]" + " [SERVER/INFO] Client " + str(self.address) + " has disconnected: Illegal User or Password.") self.onDisconnect() else: self.send( encoders.CONNACK_Encoder( 0, definition.ConnackReturnCode. REFUSED_UNAUTHORIZED)) print("[" + getTime() + "]" + " [SERVER/INFO] Client " + str(self.address) + " has disconnected: Unauthorized user.") self.onDisconnect() else: self.send( encoders.CONNACK_Encoder( 0, definition.ConnackReturnCode. REFUSED_ILLEGAL_CLIENTID)) print("[" + getTime() + "]" + " [SERVER/INFO] Client " + str(self.address) + " has disconnected: Illegal ClientId.") self.onDisconnect() elif messageType == definition.messageType.SUBSCRIBE: print("[" + getTime() + "]" + " [SERVER/INFO] Client " + str(self.address) + " subscribing...") packetIdentifier = results['packetIdentifier'] topics = results['topics'] returnCodes = [] for i in range(0, topics.__len__()): removeSubscribe(self.clientId, topics[i]['topic']) addSubscribe(self.clientId, topics[i]['topic'], topics[i]['qos']) returnCodes.append(topics[i]['qos']) self.send( encoders.SUBACK_Encoder(packetIdentifier, returnCodes)) print("[" + getTime() + "]" + " [SERVER/INFO] Client " + str(self.address) + " subscribed.") print("[" + getTime() + "]" + " [SERVER/INFO] Current subscirbes: " + str(getAllSubscribe()) + " .") elif messageType == definition.messageType.UNSUBSCRIBE: print("[" + getTime() + "]" + " [SERVER/INFO] Client " + str(self.address) + " unsubscribing...") packetIdentifier = results['packetIdentifier'] topics = results['topics'] for i in range(0, topics.__len__()): removeSubscribe(self.clientId, topics[i]) self.send(encoders.UNSUBACK_Encoder(packetIdentifier)) print("[" + getTime() + "]" + " [SERVER/INFO] Client " + str(self.address) + " unsubscribed.") print("[" + getTime() + "]" + " [SERVER/INFO] Current subscirbes: " + str(getAllSubscribe()) + " .") elif messageType == definition.messageType.PINGREQ: print("[" + getTime() + "]" + " [SERVER/INFO] Client " + str(self.address) + " sent a heartbeat.") self.send(encoders.PINGRESP_Encoder()) elif messageType == definition.messageType.PUBLISH: print("[" + getTime() + "]" + " [SERVER/INFO] Client " + str(self.address) + " sent a message.") messageQueue.put({ 'retain': results['retain'], 'topic': results['topic'], 'message': results['message'] }) if results['qos'] == 1: self.send( encoders.PUBACK_Encoder(results['packetIdentifier'])) print("[" + getTime() + "]" + " [SERVER/INFO] PUBACK responded to Client " + str(self.address) + " at packet " + str(results['packetIdentifier']) + " .") elif results['qos'] == 2: self.send( encoders.PUBREC_Encoder(results['packetIdentifier'])) print("[" + getTime() + "]" + " [SERVER/INFO] PUBREC responded to Client " + str(self.address) + " at packet " + str(results['packetIdentifier']) + " .") elif messageType == definition.messageType.PUBREL: self.send(encoders.PUBCOMP_Encoder( results['packetIdentifier'])) print("[" + getTime() + "]" + " [SERVER/INFO] PUBCOMP responded to Client " + str(self.address) + " at packet " + str(results['packetIdentifier']) + " .") elif messageType == definition.messageType.PUBACK: print("[" + getTime() + "]" + " [SERVER/INFO] Client " + str(self.address) + " responded a PUBACK.") clientId = self.clientId packetIdentifier = results['packetIdentifier'] try: for i in range(0, timeoutTimers.__len__()): if timeoutTimers[i][ 'packetIdentifier'] == packetIdentifier and timeoutTimers[ i]['clientId'] == clientId and timeoutTimers[ i]['waitingFor'] == 'PUBACK': timeoutTimers[i]['timer'].cancel() except: pass elif messageType == definition.messageType.PUBREC: print("[" + getTime() + "]" + " [SERVER/INFO] Client " + str(self.address) + " responded a PUBREC.") clientId = self.clientId packetIdentifier = results['packetIdentifier'] self.send(encoders.PUBREL_Encoder(packetIdentifier)) print("[" + getTime() + "]" + " [SERVER/INFO] PUBREL responded to Client " + str(self.address) + " at packet " + str(packetIdentifier) + " .") try: for i in range(0, timeoutTimers.__len__()): if timeoutTimers[i][ 'packetIdentifier'] == packetIdentifier and timeoutTimers[ i]['clientId'] == clientId and timeoutTimers[ i]['waitingFor'] == 'PUBREC': timeoutTimers[i]['timer'].cancel() break timer = threading.Timer(ACK_TIMEOUT, self.pubcompNotReceived) timeoutTimers.append({ 'clientId': self.getClientId(), 'packetIdentifier': packetIdentifier, 'waitingFor': 'PUBCOMP', 'timer': timer }) timer.start() except: pass elif messageType == definition.messageType.PUBCOMP: print("[" + getTime() + "]" + " [SERVER/INFO] Client " + str(self.address) + " responded a PUBCOMP.") clientId = self.clientId packetIdentifier = results['packetIdentifier'] try: for i in range(0, timeoutTimers.__len__()): if timeoutTimers[i][ 'packetIdentifier'] == packetIdentifier and timeoutTimers[ i]['clientId'] == clientId and timeoutTimers[ i]['waitingFor'] == 'PUBCOMP': timeoutTimers[i]['timer'].cancel() break except: pass elif messageType == definition.messageType.DISCONNECT: self.onDisconnect() print("[" + getTime() + "]" + " [SERVER/INFO] Client " + str(self.address) + " has disconnected.") except decoders.IllegalMessageException: print(data) print("[" + getTime() + "]" + " [SERVER/INFO] Client " + str(self.address) + " has disconnected: Illegal Message Received.") self.onDisconnect()
def publishFromQueue(): """ Description: 从线程安全的messageQueue中按队列顺序发送消息。 Args: None Returns: None Raises: IOException socket连接异常。 """ while True: if messageQueue.qsize() != 0: messageItem = messageQueue.get() subscribers = getSubscribers(messageItem['topic']) for i in range(0, subscribers.__len__()): subscriber = subscribers[i][0] qos = subscribers[i][2] connectionsLock.acquire() if qos == 0: for j in range(0, connections.__len__()): if connections[j].getClientId() == subscriber: connections[j].send( encoders.PUBLISH_Encoder( 0, qos, 0, messageItem['topic'], 0, messageItem['message'])) elif qos == 1: packetIdentifier = generatePacketIdentifier() for j in range(0, connections.__len__()): if connections[j].getClientId() == subscriber: connections[j].send( encoders.PUBLISH_Encoder( 0, qos, 0, messageItem['topic'], packetIdentifier, messageItem['message'])) timer = threading.Timer(ACK_TIMEOUT, pubackNotReceived, [ connections[j], ]) timeoutTimers.append({ 'clientId': connections[j].getClientId(), 'packetIdentifier': packetIdentifier, 'waitingFor': 'PUBACK', 'timer': timer }) timer.start() elif qos == 2: packetIdentifier = generatePacketIdentifier() for j in range(0, connections.__len__()): if connections[j].getClientId() == subscriber: connections[j].send( encoders.PUBLISH_Encoder( 0, qos, 0, messageItem['topic'], packetIdentifier, messageItem['message'])) timer = threading.Timer(ACK_TIMEOUT, pubrecNotReceived, [ connections[j], ]) timeoutTimers.append({ 'clientId': connections[j].getClientId(), 'packetIdentifier': packetIdentifier, 'waitingFor': 'PUBREC', 'timer': timer }) timer.start() connectionsLock.release() if messageItem['retain'] == 1: addRetain(messageItem) print("[" + getTime() + "]" + " [SERVER/INFO] Queue processed a message." + str(messageQueue.qsize()) + " message(s) in queue, " + str(retainedMessages.__len__()) + " message(s) retained.")