コード例 #1
0
class ServerThread(QThread):
    def __init__(self, ip, port, console):
        super().__init__()
        self.ip = ip
        self.port = port
        self.tcpServer = QTcpServer()
        self.clientList = []
        address = QHostAddress(self.ip)
        if not self.tcpServer.listen(address, self.port):
            print("cant listen!")
            self.tcpServer.close()
            return
        self.tcpServer.newConnection.connect(self.addConnection)
        self.receviedDataSignal = pyqtSignal(str)
        # This generate error Attribue No attribute connect !
        # self.receviedDataSignal.connect(console.receivePacket)
    def run(self):
        self.tcpServer.moveToThread(self.thread())
        while True:
            for conn in self.clientList:
                self.echoConnection(conn)
        self.closeAllTCPClient()

    def addConnection(self):
        connectionToAdd = self.tcpServer.nextPendingConnection()
        self.clientList.append(connectionToAdd)

    def echoConnection(self, clientConnection):
        readData = self.readFromTCPSocket(clientConnection)
        print("[HOST] Received from ",
              clientConnection.localAddress().toString(),
              clientConnection.localPort())
        print(readData)
        # Add write to our console
        # self.receviedDataSignal.emit(readData)

    def readFromTCPSocket(self, tcpSocket):
        tcpSocket.waitForReadyRead()
        data = tcpSocket.readAll()
        return data

    def closeAllTCPClient(self):
        for conn in self.clientList:
            conn.disconnectFromHost()

    def readNewConnection(self):
        conn = self.tcpServer.nextPendingConnection()
        self.echoConnection(conn)
コード例 #2
0
class TeacherSessionManager(SessionManager):
    def __init__(self, gui):
        SessionManager.__init__(self, gui)
        self.session_type = SessionType.TEACHER
        self.gui = gui
        self.session_ticker = Ticker(self.tickSessionOnce, parent=gui)
        self.simulation_paused_at = None  # pause time if session is paused; None otherwise
        self.server = QTcpServer(gui)
        self.student_socket = None
        self.server.newConnection.connect(self.studentConnects)
        self.aircraft_list = []  # ControlledAircraft list
        self.current_local_weather = None  # initialised by the teaching console on sessionStarted
        self.noACK_traffic_count = 0

    def start(self):
        self.aircraft_list.clear()
        self.simulation_paused_at = None
        self.session_ticker.start_stopOnZero(teacher_ticker_interval)
        self.server.listen(port=settings.teaching_service_port)
        print('Teaching server ready on port %d' %
              settings.teaching_service_port)
        signals.specialTool.connect(self.createNewTraffic)
        signals.kbdPTT.connect(self.sendPTT)
        signals.sessionStarted.emit()

    def stop(self):
        if self.isRunning():
            self.session_ticker.stop()
            if self.studentConnected():
                self.shutdownStudentConnection()
            signals.specialTool.disconnect(self.createNewTraffic)
            signals.kbdPTT.disconnect(self.sendPTT)
            self.server.close()
            self.aircraft_list.clear()
            signals.sessionEnded.emit()

    def studentConnected(self):
        return self.student_socket != None

    def isRunning(self):
        return self.session_ticker.isActive(
        ) or self.simulation_paused_at != None

    def myCallsign(self):
        return teacher_callsign

    def getAircraft(self):
        return self.aircraft_list[:]

    def getWeather(self, station):
        return self.current_local_weather if station == settings.primary_METAR_station else None

    def postRadioChatMsg(self, msg):
        raise ValueError(
            'Public radio chat panel reserved for monitoring read-backs in teacher sessions. '
            'Use the ATC text chat system to communicate with the student.')

    def postAtcChatMsg(self, msg):
        if self.studentConnected():
            if msg.isPrivate():
                payload = '%s\n%s' % (msg.sender(), msg.txtOnly())
                self.student.sendMessage(
                    TeachingMsg(TeachingMsg.ATC_TEXT_CHAT, data=payload))
            else:
                raise ValueError(
                    'Only private messaging is enabled in tutoring sessions.')
        else:
            raise ValueError('No student connected.')

    ## CONNECTION MANAGEMENT

    def studentConnects(self):
        new_connection = self.server.nextPendingConnection()
        if new_connection:
            peer_address = new_connection.peerAddress().toString()
            print('Contacted by %s' % peer_address)
            if self.studentConnected():
                new_connection.disconnectFromHost()
                print('Client rejected. Student already connected.')
            else:
                self.student_socket = new_connection
                self.student_socket.disconnected.connect(
                    self.studentDisconnects)
                self.student_socket.disconnected.connect(
                    self.student_socket.deleteLater)
                self.student = TeachingSessionWire(self.student_socket)
                self.student.messageArrived.connect(self.receiveMsgFromStudent)
                env.ATCs.updateATC(student_callsign, None, None, None)
                self.noACK_traffic_count = 0
                self.sendWeather()
                self.sendATCs()
                self.tickSessionOnce()
                if self.simulation_paused_at != None:
                    self.student.sendMessage(
                        TeachingMsg(TeachingMsg.SIM_PAUSED))
                QMessageBox.information(
                    self.gui, 'Student connection',
                    'Student accepted from %s' % peer_address)
        else:
            print('WARNING: Connection attempt failed.')

    def studentDisconnects(self):
        self.shutdownStudentConnection()
        QMessageBox.information(self.gui, 'Student disconnection',
                                'Your student has disconnected.')

    def shutdownStudentConnection(self):
        self.student_socket.disconnected.disconnect(self.studentDisconnects)
        env.cpdlc.endAllDataLinks()
        env.ATCs.removeATC(student_callsign)
        self.student.messageArrived.disconnect(self.receiveMsgFromStudent)
        self.student_socket.disconnectFromHost()
        self.student_socket = None

    ## TEACHER MANAGEMENT

    def instructAircraftByCallsign(self, callsign, instr):
        try:
            acft = next(acft for acft in self.aircraft_list
                        if acft.identifier == callsign)
        except StopIteration:
            print('ERROR: Teacher aircraft not found: %s' % callsign)
            return
        try:
            acft.instruct([instr])
            acft.readBack([instr])
        except Instruction.Error as err:
            QMessageBox.critical(self.gui, 'Instruction error',
                                 speech_str2txt(str(err)))

    def createNewTraffic(self, spawn_coords, spawn_hdg):
        dialog = CreateTrafficDialog(spawn_coords, spawn_hdg, parent=self.gui)
        dialog.exec()
        if dialog.result() > 0:
            params = dialog.acftInitParams()
            params.XPDR_mode = new_traffic_XPDR_mode
            acft = ControlledAircraft(dialog.acftCallsign(), dialog.acftType(),
                                      params, None)
            acft.spawned = False
            acft.frozen = dialog.startFrozen()
            acft.tickOnce()
            self.aircraft_list.append(acft)
            if dialog.createStrip():
                strip = Strip()
                strip.writeDetail(FPL.CALLSIGN, acft.identifier)
                strip.writeDetail(FPL.ACFT_TYPE, acft.aircraft_type)
                strip.writeDetail(FPL.WTC, wake_turb_cat(acft.aircraft_type))
                strip.linkAircraft(acft)
                signals.receiveStrip.emit(strip)
            selection.selectAircraft(acft)

    def killAircraft(self, acft):
        if env.cpdlc.isConnected(acft.identifier):
            env.cpdlc.endDataLink(acft.identifier)
        pop_all(self.aircraft_list, lambda a: a is acft)
        if acft.spawned and self.studentConnected():
            self.student.sendMessage(
                TeachingMsg(TeachingMsg.ACFT_KILLED, data=acft.identifier))
        signals.aircraftKilled.emit(acft)

    def sendATCs(self):
        if self.studentConnected():
            msg = TeachingMsg(TeachingMsg.SX_LIST)
            for atc in env.ATCs.knownATCs(
                    lambda atc: atc.callsign != student_callsign):
                try:
                    frq = env.ATCs.getATC(
                        atc
                    ).frequency  # instance of CommFrequency class, or None
                except KeyError:
                    frq = None
                msg.appendData(atc if frq == None else '%s\t%s' % (atc, frq))
                msg.appendData('\n')
            self.student.sendMessage(msg)

    def setWeather(self, weather):  # assumed at primary location and newer
        self.current_local_weather = weather
        signals.newWeather.emit(settings.primary_METAR_station,
                                self.current_local_weather)
        self.sendWeather()

    def sendWeather(self):
        if self.studentConnected() and self.current_local_weather != None:
            self.student.sendMessage(
                TeachingMsg(TeachingMsg.WEATHER,
                            data=self.current_local_weather.METAR()))

    def sendPTT(self, ignore_button, on_off):
        if selection.acft != None and selection.acft.spawned:
            if on_off:
                env.rdf.receiveSignal(
                    selection.acft.identifier,
                    lambda acft=selection.acft: acft.coords())
            else:
                env.rdf.dieSignal(selection.acft.identifier)
            if self.studentConnected():
                str_data = '%d %s' % (on_off, selection.acft.identifier)
                self.student.sendMessage(
                    TeachingMsg(TeachingMsg.PTT, data=str_data))

    def requestCpdlcConnection(
            self, callsign):  # NOTE: student must confirm data link
        if self.studentConnected():
            self.student.sendMessage(
                TeachingMsg(TeachingMsg.CPDLC, data=('%s\n1' % callsign)))

    def transferCpdlcAuthority(
        self, acft_callsign, atc_callsign
    ):  # for teacher, ATC here is who to transfer *from* to student
        if self.studentConnected():
            self.student.sendMessage(TeachingMsg(TeachingMsg.CPDLC, \
              data=('%s\n%s%s' % (acft_callsign, CPDLC_transfer_cmd_prefix, atc_callsign)))) # NOTE: student must confirm data link

    def disconnectCpdlc(self, callsign):
        env.cpdlc.endDataLink(callsign)
        if self.studentConnected():
            self.student.sendMessage(
                TeachingMsg(TeachingMsg.CPDLC, data=('%s\n0' % callsign)))

    def sendCpdlcMsg(self, callsign, msg):
        link = env.cpdlc.currentDataLink(callsign)
        if link == None:
            return
        if msg.type() == CpdlcMessage.ACK and link.msgCount() > 0:
            last_msg = link.lastMsg()
            if not last_msg.isFromMe() and last_msg.type() == CpdlcMessage.INSTR \
              and yesNo_question(self.gui, 'ACK after received INSTR', last_msg.contents(), 'Execute instruction?'):
                try:
                    instr = Instruction.fromEncodedStr(last_msg.contents())
                    self.instructAircraftByCallsign(callsign, instr)
                except ValueError:  # raised by Instruction.fromEncodedStr
                    if not yesNo_question(self.gui, 'CPDLC comm error', \
                      'Unable to decode instruction.', 'Send ACK and perform manually?'):
                        return  # cancel sending any message
                except Instruction.Error as err:  # raised by TeacherSessionManager.instructAircraftByCallsign
                    if not yesNo_question(self.gui, 'CPDLC instruction error', \
                      'Unable to perform instruction: %s' % err, 'Send ACK anyway?'):
                        return  # cancel sending any message
                else:  # no problem executing instruction
                    selection.writeStripAssignment(instr)
        if self.studentConnected() and link != None:
            link.appendMessage(msg)
            self.student.sendMessage(
                TeachingMsg(
                    TeachingMsg.CPDLC,
                    data=('%s\n%s%s' %
                          (callsign, CPDLC_message_cmd_prefix, msg.text()))))

    def pauseSession(self):
        self.session_ticker.stop()
        self.simulation_paused_at = now()
        signals.sessionPaused.emit()
        if self.studentConnected():
            self.student.sendMessage(TeachingMsg(TeachingMsg.SIM_PAUSED))

    def resumeSession(self):
        pause_delay = now() - self.simulation_paused_at
        for acft in self.aircraft_list:
            acft.moveHistoryTimesForward(pause_delay)
        self.simulation_paused_at = None
        self.session_ticker.start_stopOnZero(teacher_ticker_interval)
        signals.sessionResumed.emit()
        if self.studentConnected():
            self.student.sendMessage(TeachingMsg(TeachingMsg.SIM_RESUMED))

    ## MESSAGES FROM STUDENT

    def receiveMsgFromStudent(self, msg):
        #DEBUG if msg.type != TeachingMsg.TRAFFIC:
        #DEBUG 	print('=== TEACHERS RECEIVES ===\n%s\n=== End ===' % msg.data)
        if msg.type == TeachingMsg.ATC_TEXT_CHAT:
            lines = msg.strData().split('\n')
            if len(lines) == 2:
                signals.incomingAtcTextMsg.emit(
                    ChatMessage(student_callsign,
                                lines[1],
                                recipient=lines[0],
                                private=True))
            else:
                print(
                    'ERROR: Invalid format in received ATC text chat from student.'
                )
        elif msg.type == TeachingMsg.STRIP_EXCHANGE:
            line_sep = msg.strData().split('\n', maxsplit=1)
            toATC = line_sep[0]
            strip = Strip.fromEncodedDetails(
                '' if len(line_sep) < 2 else line_sep[1])
            strip.writeDetail(received_from_detail, student_callsign)
            if toATC != teacher_callsign:
                strip.writeDetail(sent_to_detail, toATC)
            signals.receiveStrip.emit(strip)
        elif msg.type == TeachingMsg.WEATHER:  # requesting weather information
            if msg.strData() == settings.primary_METAR_station:
                self.sendWeather()
        elif msg.type == TeachingMsg.TRAFFIC:  # acknowledging a traffic message
            if self.noACK_traffic_count > 0:
                self.noACK_traffic_count -= 1
            else:
                print('ERROR: Student acknowledging unsent traffic?!')

        elif msg.type == TeachingMsg.CPDLC:
            # Msg format in 2 lines, first being ACFT callsign, second is either of the following:
            #  - connect/disconnect: "0" or "1"
            #  - data authority transfer: CPDLC_transfer_cmd_prefix + ATC callsign transferring to/from
            #  - other: CPDLC_message_cmd_prefix + encoded message string
            try:
                acft_callsign, line2 = msg.strData().split('\n', maxsplit=1)
                if line2 == '0':  # ACFT disconnected by student
                    if env.cpdlc.isConnected(acft_callsign):
                        env.cpdlc.endDataLink(acft_callsign)
                    else:  # student is rejecting a connection (unable CPDLC)
                        QMessageBox.warning(
                            self.gui, 'CPDLC connection failed',
                            'Student is not accepting CPDLC connections.')
                elif line2 == '1':  # student confirming ACFT log-on
                    env.cpdlc.beginDataLink(acft_callsign, student_callsign)
                elif line2.startswith(
                        CPDLC_transfer_cmd_prefix
                ):  # student transferring or confirming transfer
                    atc = line2[len(CPDLC_transfer_cmd_prefix):]
                    if env.cpdlc.isConnected(
                            acft_callsign
                    ):  # student initiating transfer to next ATC
                        env.cpdlc.endDataLink(acft_callsign, transferTo=atc)
                    else:  # student confirming proposed transfer
                        env.cpdlc.beginDataLink(acft_callsign,
                                                student_callsign,
                                                transferFrom=atc)
                elif line2.startswith(CPDLC_message_cmd_prefix
                                      ):  # student ATC sent a message
                    encoded_msg = line2[len(CPDLC_message_cmd_prefix):]
                    link = env.cpdlc.currentDataLink(acft_callsign)
                    if link == None:
                        print(
                            'Ignored CPDLC message sent to %s while not connected.'
                            % acft_callsign)
                    else:
                        link.appendMessage(
                            CpdlcMessage.fromText(False, encoded_msg))
                else:
                    print('Error decoding CPDLC command from student:', line2)
            except (IndexError, ValueError):
                print('Error decoding CPDLC message value from student')
        else:
            print('ERROR: Unhandled message type from student: %s' % msg.type)

    ## TICK

    def tickSessionOnce(self):
        pop_all(self.aircraft_list,
                lambda a: not env.pointInRadarRange(a.params.position))
        send_traffic_this_tick = self.studentConnected(
        ) and self.noACK_traffic_count < max_noACK_traffic
        for acft in self.aircraft_list:
            acft.tickOnce()
            fgms_packet = acft.fgmsLivePositionPacket()
            send_packet_to_views(fgms_packet)
            if send_traffic_this_tick and acft.spawned:
                self.student.sendMessage(
                    TeachingMsg(TeachingMsg.TRAFFIC, data=fgms_packet))
                self.noACK_traffic_count += 1

    ## STRIP EXCHANGE

    def stripDroppedOnATC(self, strip, sendto):
        if sendto == student_callsign:
            items = [teacher_callsign] + env.ATCs.knownATCs(
                lambda atc: atc.callsign != student_callsign)
            sender, ok = QInputDialog.getItem(self.gui,
                                              'Send strip to student',
                                              'Hand over strip from:',
                                              items,
                                              editable=False)
            if ok and self.studentConnected():
                msg_data = sender + '\n' + strip.encodeDetails(
                    handover_details)
                self.student.sendMessage(
                    TeachingMsg(TeachingMsg.STRIP_EXCHANGE, data=msg_data))
            else:
                raise HandoverBlocked('Cancelled by teacher.', silent=True)
        else:
            raise HandoverBlocked('Strips can only be sent to the student!')

    ## SNAPSHOTTING

    def situationSnapshot(self):
        return [acft.statusSnapshot() for acft in self.aircraft_list]

    def restoreSituation(self, situation_snapshot):
        while self.aircraft_list != []:
            self.killAircraft(self.aircraft_list[0])
        for acft_snapshot in situation_snapshot:
            self.aircraft_list.append(
                ControlledAircraft.fromStatusSnapshot(acft_snapshot))
        self.tickSessionOnce()
コード例 #3
0
class TcpS(QDialog, Ui_TcpServer):
    """
    文件传输服务器
    """

    sendFileName = pyqtSignal(str)

    def __init__(self, parent=None):
        """
        一些初始设置
        """
        super(TcpS, self).__init__(parent)
        self.setupUi(self)
        self.payloadSize = 64 * 1024
        # 读取数据64KB

        self.totalBytes = 0
        # 总大小

        self.bytesWritten = 0
        # 保存的数据

        self.bytesToWrite = 0
        # 每次减少连接写的数据量大小

        self.theFileName = ""
        # 文件名(不含路径)

        self.fileName = ""
        # 文件全名

        self.localFile = QFile()
        self.outBlock = QByteArray()
        # QByteArray()的对象,即字节数组

        self.time = QTime()
        self.initServer()

    def initServer(self):
        """
        网络设置初始化
        """
        self.tcpPort = 7788
        # 指定了TCP端口为7788

        self.tcpServer = QTcpServer(self)
        self.clientConnection = QTcpSocket(self)
        # 创建一个Tcp服务器和一个Tcp套接字

        self.tcpServer.newConnection.connect(self.sendMessage)
        # 当有新的连接来的时候发出newConnection信号,我们连接到sendMessage()函数。

        self.serverStatuslabel.setText("请选择要传送的文件")
        self.progressBar.reset()
        self.serverOpenBtn.setEnabled(True)
        self.serverSendBtn.setEnabled(False)
        self.tcpServer.close()
        # 显示我们开始创建的对话框,打开按钮是可用的,发送按钮是不可用的,进度条复位,先关闭服务器。

    def refused(self):
        """
        对端拒绝接收文件,主程序会调用服务器的refused()函数,关闭服务器。
        """
        self.tcpServer.close()
        self.serverStatuslabel.setText("对方拒绝接收")

    def closeEvent(self, event):
        """
        关闭事件
        """
        self.on_serverCloseBtn_clicked()
        # 产生关闭事件,直接调用关闭窗口按钮函数。

    def sendMessage(self):
        """
        发送文件
        """
        self.serverSendBtn.setEnabled(False)
        # 发送按钮不可用

        self.clientConnection = self.tcpServer.nextPendingConnection()
        # self.clientConnection作为连接的QTcpSocket对象返回下一个挂起的连接。

        self.clientConnection.bytesWritten.connect(self.updateClientProgress)
        # 当连接中每次将数据有效载荷写入设备的当前写通道时,都会发出此信号。在此有效负载中写入的数据量为字节数。

        self.serverStatuslabel.setText("开始传送文件 {} !".format(self.theFileName))

        self.localFile = QFile(self.fileName)
        if not (self.localFile.open(QFile.ReadOnly)):
            errorMsg = "无法读取文件 {}:\n {}".format(self.fileName,
                                                self.localFile.errorString())
            QMessageBox.warning(self, "应用程序", errorMsg)
            return
        # 尝试打开文件,要是存在问题就报错。

        self.serverCloseBtn.setText("取消")

        self.totalBytes = self.localFile.size()
        # 记录一下需要传输的文件大小。单位:字节

        sendOut = QDataStream(self.outBlock, QIODevice.WriteOnly)
        # 这里的self.outBlock是QByteArray()的对象,即字节数组;QIODevice的模式为WriteOnly

        sendOut.setVersion(QDataStream.Qt_5_4)
        # 设定QDataStream的版本为Qt_5_4

        self.time.start()
        # 开始计时

        currentFile = self.fileName.split("/")[-1]
        # 传输的文件名

        sendOut.writeInt64(0)
        sendOut.writeInt64(0)
        sendOut.writeQString(currentFile)
        self.totalBytes += self.outBlock.size()
        # 在sendOut中写入文件名以及文件名和文件的大小,大小都是以字节为单位的。

        sendOut.device().seek(0)
        sendOut.writeInt64(self.totalBytes)
        sendOut.writeInt64(self.outBlock.size() - 2)
        # QIODevice读写位置移动到0。然后分别写入总的大小和文件名大小。

        self.bytesToWrite = self.totalBytes - self.clientConnection.write(
            self.outBlock)
        # 待传输文件的大小。

        self.outBlock.resize(0)
        # outBlock清零。

    def updateClientProgress(self, numBytes):
        """
        发送进度显示
        """
        qApp.processEvents()
        # 长时间工作用,以免窗口假死

        self.bytesWritten += numBytes
        if self.bytesWritten > 0:
            self.block = self.localFile.read(
                min(self.bytesToWrite, self.payloadSize))
            self.bytesToWrite -= self.clientConnection.write(self.block)
        else:
            self.localFile.close()
        # 当我们待写入的字节数大于0时,我们每次读取的数据都是小于等于self.payloadSize的,这个self.payloadSize我们定义是64KB。
        # self.bytesToWrite每次减少连接写的数据量大小。
        # 要是待写入的字节数小于等于0,则关闭文件。

        byteSent = self.bytesWritten / (1024 * 1024)
        # 已经写了多少文件
        useTime = self.time.elapsed() / 1000
        # 传输用了多长时间
        speed = self.bytesWritten / useTime / (1024 * 1024)
        # 传输速度
        total = self.totalBytes / (1024 * 1024)
        # 总大小
        left = (total - byteSent) / speed
        # 表示剩余时间

        if byteSent < 0.01:
            byteSent = self.bytesWritten / 1024
            speed = self.bytesWritten / useTime / 1024
            total = self.totalBytes / 1024
            if left > 0:
                sendInfo = "已发送 {0:.2f}KB({1:.2f}KB/s)\n共{2:.2f}KB 已用时:{3:.1f}秒\n 估计剩余时间:{4:.1f}秒".format(
                    byteSent, speed, total, useTime, left)
            else:
                sendInfo = "已发送 {0:.2f}KB({1:.2f}KB/s)\n共{2:.2f}KB 用时:{3:.1f}秒\n".format(
                    byteSent, speed, total, useTime)
        else:
            if left > 0:
                sendInfo = "已发送 {0:.2f}MB({1:.2f}MB/s)\n共{2:.2f}MB 已用时:{3:.1f}秒\n 估计剩余时间:{4:.1f}秒".format(
                    byteSent, speed, total, useTime, left)
            else:
                sendInfo = "已发送 {0:.2f}MB({1:.2f}MB/s)\n共{2:.2f}MB 用时:{3:.1f}秒\n".format(
                    byteSent, speed, total, useTime)

        self.progressBar.setMaximum(total)
        self.progressBar.setValue(byteSent)

        if self.bytesWritten == self.totalBytes:
            self.serverCloseBtn.setText("关闭")
        # 进度条显示的方式,以及当传输的字节数等于总的字节数的时候,按钮就显示关闭。

        self.serverStatuslabel.setText(sendInfo)

    @pyqtSlot()
    def on_serverOpenBtn_clicked(self):
        """
        打开文件准备发送
        """
        self.fileName = QFileDialog.getOpenFileName(self, '打开文件', './')[0]
        if self.fileName:
            self.theFileName = self.fileName.split("/")[-1]
            self.serverStatuslabel.setText("要传送的文件为:{}".format(
                self.theFileName))
            self.serverSendBtn.setEnabled(True)
            self.serverOpenBtn.setEnabled(False)

    @pyqtSlot()
    def on_serverSendBtn_clicked(self):
        """
        发送文件,等待接收
        """
        if not (self.tcpServer.listen(QHostAddress.Any, self.tcpPort)):
            errorMsg = self.tcpServer.errorString()
            QMessageBox.warning(self, "错误", "发送失败:\n {}".format(errorMsg))
            self.TcpServer.close()
            return

        self.serverStatuslabel.setText("等待对方接收... ...")
        self.serverSendBtn.setEnabled(False)
        self.sendFileName.emit(self.theFileName)

    @pyqtSlot()
    def on_serverCloseBtn_clicked(self):
        """
        取消或者关闭
        """
        if self.tcpServer.isListening():
            self.tcpServer.close()
            if self.localFile.isOpen():
                self.localFile.close()
            self.clientConnection.abort()

        if self.serverCloseBtn.text() == "取消":
            self.serverCloseBtn.setText("关闭")
        else:
            self.close()
            self.serverOpenBtn.setEnabled(True)
            self.serverSendBtn.setEnabled(False)
            self.progressBar.reset()
            self.totalBytes = 0
            self.bytesWritten = 0
            self.bytesToWrite = 0
            self.serverStatuslabel.setText("请选择要传送的文件")
コード例 #4
0
class Server(QWidget):
    def __init__(self):
        QWidget.__init__(self)

        self.serverOpen = False
        self.tcpServer = None
        self.tcpServerConnection = None

        self.textEdit = None
        self.lineEdit = None

        self.create_widgets()

    def create_widgets(self):
        self.tcpServer = QTcpServer()

        self.textEdit = QTextEdit()
        self.textEdit.setReadOnly(True)

        self.lineEdit = QLineEdit()
        self.lineEdit.setPlaceholderText("Enter response")
        self.lineEdit.setMaxLength(50)
        self.lineEdit.setEnabled(True)

        vBox = QVBoxLayout()
        vBox.addWidget(self.textEdit)
        vBox.addWidget(self.lineEdit)
        self.setLayout(vBox)

        self.tcpServer.newConnection.connect(self.accept_connection)

    def add_message(self, message):
        self.textEdit.moveCursor(QTextCursor.End)
        self.textEdit.insertPlainText(message)
        self.textEdit.moveCursor(QTextCursor.End)

    def open_server(self):
        if (len(self.lineEdit.text()) == 0):
            self.add_message("You must enter a response\n")
            QMessageBox.critical(self, "Error", "You must enter a response")
            return False

        self.tcpServer.listen(QHostAddress(__serverUrl__), 9000)

        self.serverOpen = self.tcpServer.isListening()

        if (self.serverOpen):
            serverAddress = self.tcpServer.serverAddress().toString()
            serverPort = self.tcpServer.serverPort()
            self.add_message("Server opened on %s on port %d\n" %
                             (serverAddress, serverPort))
            self.lineEdit.setEnabled(False)
        else:
            self.add_message(self.tcpServer.errorString())
            QMessageBox.critical(self, "Error", self.tcpServer.errorString())

        return True

    def accept_connection(self):
        self.tcpServerConnection = self.tcpServer.nextPendingConnection()
        self.tcpServerConnection.readyRead.connect(self.receive_data)
        self.tcpServerConnection.disconnected.connect(self.socket_disconnected)

        peerAddress = self.tcpServerConnection.peerAddress().toString()
        peerPort = self.tcpServerConnection.peerPort()
        self.add_message("Connected to %s on port %d\n" %
                         (peerAddress, peerPort))

    def receive_data(self):
        rxData = self.tcpServerConnection.readAll()
        self.add_message("Received '" + rxData.data().decode('utf8') + "'\n")
        txString = self.lineEdit.text()
        self.tcpServerConnection.write(txString.encode())
        self.add_message("Wrote '" + txString + "'\n")

    def socket_disconnected(self):
        self.add_message("Disconnected from client\n")

    def close_server(self):
        if (self.serverOpen):
            self.tcpServer.close()
            self.lineEdit.setEnabled(True)
コード例 #5
0
class Dialog(QDialog):
    TotalBytes = 50 * 1024 * 1024
    PayloadSize = 65536

    def __init__(self, parent=None):
        super(Dialog, self).__init__(parent)

        self.tcpServer = QTcpServer()
        self.tcpClient = QTcpSocket()
        self.bytesToWrite = 0
        self.bytesWritten = 0
        self.bytesReceived = 0

        self.clientProgressBar = QProgressBar()
        self.clientStatusLabel = QLabel("Client ready")
        self.serverProgressBar = QProgressBar()
        self.serverStatusLabel = QLabel("Server ready")

        self.startButton = QPushButton("&Start")
        self.quitButton = QPushButton("&Quit")

        buttonBox = QDialogButtonBox()
        buttonBox.addButton(self.startButton, QDialogButtonBox.ActionRole)
        buttonBox.addButton(self.quitButton, QDialogButtonBox.RejectRole)

        self.startButton.clicked.connect(self.start)
        self.quitButton.clicked.connect(self.close)
        self.tcpServer.newConnection.connect(self.acceptConnection)
        self.tcpClient.connected.connect(self.startTransfer)
        self.tcpClient.bytesWritten.connect(self.updateClientProgress)
        self.tcpClient.error.connect(self.displayError)

        mainLayout = QVBoxLayout()
        mainLayout.addWidget(self.clientProgressBar)
        mainLayout.addWidget(self.clientStatusLabel)
        mainLayout.addWidget(self.serverProgressBar)
        mainLayout.addWidget(self.serverStatusLabel)
        mainLayout.addStretch(1)
        mainLayout.addSpacing(10)
        mainLayout.addWidget(buttonBox)
        self.setLayout(mainLayout)

        self.setWindowTitle("Loopback")

    def start(self):
        self.startButton.setEnabled(False)

        QApplication.setOverrideCursor(Qt.WaitCursor)

        self.bytesWritten = 0
        self.bytesReceived = 0

        while not self.tcpServer.isListening() and not self.tcpServer.listen():
            ret = QMessageBox.critical(
                self,
                "Loopback",
                "Unable to start the test: %s." % self.tcpServer.errorString(),
                QMessageBox.Retry | QMessageBox.Cancel,
            )
            if ret == QMessageBox.Cancel:
                return

        self.serverStatusLabel.setText("Listening")
        self.clientStatusLabel.setText("Connecting")

        self.tcpClient.connectToHost(QHostAddress(QHostAddress.LocalHost),
                                     self.tcpServer.serverPort())

    def acceptConnection(self):
        self.tcpServerConnection = self.tcpServer.nextPendingConnection()
        self.tcpServerConnection.readyRead.connect(self.updateServerProgress)
        self.tcpServerConnection.error.connect(self.displayError)

        self.serverStatusLabel.setText("Accepted connection")
        self.tcpServer.close()

    def startTransfer(self):
        self.bytesToWrite = Dialog.TotalBytes - self.tcpClient.write(
            QByteArray(Dialog.PayloadSize, "@"))
        self.clientStatusLabel.setText("Connected")

    def updateServerProgress(self):
        self.bytesReceived += self.tcpServerConnection.bytesAvailable()
        self.tcpServerConnection.readAll()

        self.serverProgressBar.setMaximum(Dialog.TotalBytes)
        self.serverProgressBar.setValue(self.bytesReceived)
        self.serverStatusLabel.setText("Received %dMB" % (self.bytesReceived /
                                                          (1024 * 1024)))

        if self.bytesReceived == Dialog.TotalBytes:
            self.tcpServerConnection.close()
            self.startButton.setEnabled(True)
            QApplication.restoreOverrideCursor()

    def updateClientProgress(self, numBytes):
        self.bytesWritten += numBytes
        if self.bytesToWrite > 0:
            self.bytesToWrite -= self.tcpClient.write(
                QByteArray(min(self.bytesToWrite, Dialog.PayloadSize), "@"))

        self.clientProgressBar.setMaximum(Dialog.TotalBytes)
        self.clientProgressBar.setValue(self.bytesWritten)
        self.clientStatusLabel.setText("Sent %dMB" % (self.bytesWritten /
                                                      (1024 * 1024)))

    def displayError(self, socketError):
        if socketError == QTcpSocket.RemoteHostClosedError:
            return

        QMessageBox.information(
            self,
            "Network error",
            "The following error occured: %s." % self.tcpClient.errorString(),
        )

        self.tcpClient.close()
        self.tcpServer.close()
        self.clientProgressBar.reset()
        self.serverProgressBar.reset()
        self.clientStatusLabel.setText("Client ready")
        self.serverStatusLabel.setText("Server ready")
        self.startButton.setEnabled(True)
        QApplication.restoreOverrideCursor()
コード例 #6
0
class Window(QWidget, Ui_FormFrameworkTools):
    def __init__(self, *args, **kwargs):
        super(Window, self).__init__(*args, **kwargs)
        self.setupUi(self)
        # 初始化server
        self._server = QTcpServer(self)
        self._server.newConnection.connect(self.onNewConnection)
        self._server.listen(QHostAddress.LocalHost, 49496)
        self._getPsPath()
        self._initCodeEdit()

        # 设置默认代码和参数
        self.argsEdit.setPlainText('testColor("{}")'.format(
            os.path.abspath('Resources/GM6C6860.jpg').replace('\\', '/')))

        self.codeEdit.setText(self._formatArgs(Template))

    def _formatArgs(self, code):
        code = code.replace(
            '#1#',
            os.path.abspath('Resources/ProgressBar.jsx').replace('\\', '/'))
        code = code.replace(
            '#2#',
            os.path.abspath('Resources/Core.jsx').replace('\\', '/'))
        code = code.replace(
            '#3#',
            os.path.abspath('Resources/test.jsx').replace('\\', '/'))
        return code

    def _initCodeEdit(self):
        # 初始化编辑器的工作
        self.codeEdit.setUtf8(True)
        self.codeEdit.linesChanged.connect(self.onLinesChanged)  # 行改变
        # 代码高亮
        self.codeEdit.setLexer(QsciLexerJavaScript(self))
        # 自动折叠
        self.codeEdit.setMarginType(3, QsciScintilla.SymbolMargin)
        self.codeEdit.setMarginLineNumbers(3, False)
        self.codeEdit.setMarginWidth(3, 15)
        self.codeEdit.setMarginSensitivity(3, True)
        # 显示行号
        #self.codeEdit.setMarginType(0, QsciScintilla.NumberMargin)
        self.codeEdit.setMarginLineNumbers(0, True)
        self.onLinesChanged()
        # 代码提示
        sciApi = QsciAPIs(self.codeEdit.lexer())
        sciApi.prepare()
        self.codeEdit.setAutoCompletionSource(QsciScintilla.AcsAll)  # 设置源
        self.codeEdit.setAutoCompletionCaseSensitivity(True)  # 设置自动补全大小写敏感
        self.codeEdit.setAutoCompletionThreshold(1)  # 设置每输入一个字符就会出现自动补全的提示
        # 设置字体
        self.codeEdit.setFont(QFont('Consolas', 16))
        self.codeEdit.setMarginsFont(self.codeEdit.font())
        # 设置编码
        self.codeEdit.SendScintilla(QsciScintilla.SCI_SETCODEPAGE,
                                    QsciScintilla.SC_CP_UTF8)

        self.codeEdit.setBraceMatching(QsciScintilla.StrictBraceMatch)

        # 设置当前行高亮
        self.codeEdit.setCaretLineVisible(True)
        self.codeEdit.setCaretLineBackgroundColor(Qt.lightGray)
        self.codeEdit.setCaretForegroundColor(Qt.white)

        # tab
        # table relative
        self.codeEdit.setIndentationsUseTabs(True)
        self.codeEdit.setIndentationWidth(4)
        self.codeEdit.setTabIndents(True)
        self.codeEdit.setAutoIndent(True)
        self.codeEdit.setBackspaceUnindents(True)
        self.codeEdit.setTabWidth(4)

        # indentation guides
        self.codeEdit.setIndentationGuides(True)

        # folding margin
        self.codeEdit.setFolding(QsciScintilla.PlainFoldStyle)
        self.codeEdit.setMarginWidth(2, 12)

        # 自动换行
        self.codeEdit.setWrapMode(QsciScintilla.WrapWord)

    def onLinesChanged(self):
        # 动态设置左边的边距
        self.codeEdit.setMarginWidth(
            0,
            self.codeEdit.fontMetrics().width(str(self.codeEdit.lines())) + 5)

    def _getPsPath(self):
        # 获取ps的路径
        settings = QSettings('FrameworkTools', 'Settings')
        psPath = settings.value('path', '')
        if not psPath:  # 如果没有找到自己保存的路径则去找系统安装的路径
            settings = QSettings(
                'HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\Photoshop.exe',
                QSettings.NativeFormat)
            psPath = settings.value('.', '')
        self.pathEdit.setText(psPath)

    def onNewConnection(self):
        # 当有新的连接来时
        while self._server.hasPendingConnections():
            socket = self._server.nextPendingConnection()
            socket.readyRead.connect(self.onReadyRead)
            if socket.bytesAvailable() > 0:
                # 如果已有数据发送过来
                self.doRecv(socket)

    def onReadyRead(self):
        # 准备接收数据
        socket = self.sender()
        if socket.bytesAvailable() > 0:
            self.doRecv(socket)

    def doRecv(self, socket):
        # 接收数据
        try:
            data = socket.readAll().data().decode()
            # 对数据解密
            data = xxtea.decryptFromBase64(data, '0123456789abcdef')
            method, args = data.split('|')
            self.resultEdit.append('被调用函数: {}, 参数: {}'.format(method, args))
            try:
                args = eval(args)
            except Exception as e:
                args = []
            # 动态执行函数
            if hasattr(self, method):
                getattr(self, method)(socket, *args)
        except Exception as e:
            self.resultEdit.append(str(e))

    def getCode(self, socket):
        # 传递参数的函数
        args = self.argsEdit.toPlainText().strip()
        args = xxtea.encryptToBase64(args, '0123456789abcdef') + '\n'
        print('发送加密数据: ', args)
        socket.write(args.encode())
        socket.flush()

    def showError(self, _, message):
        # 显示错误消息
        if message:
            QMessageBox.critical(self, '错误', message)

    @pyqtSlot()
    def on_selectButton_clicked(self):
        # 手动选择路径
        path, _ = QFileDialog.getOpenFileName(self, '选择Ps路径', '',
                                              'Photoshop.exe')
        if path:
            self.pathEdit.setText(path)
            settings = QSettings('FrameworkTools', 'Settings')
            settings.setValue('path', path)
            settings.sync()

    @pyqtSlot()
    def on_runButton_clicked(self):
        # 运行按钮
        code = self.codeEdit.text().strip()
        if not code:
            return
        if not code.startswith('#target'):
            code = '#target photoshop\n' + code
        path = tempfile.mktemp('.jsx')
        open(path, 'wb').write(code.encode('utf-8'))
        subprocess.call([self.pathEdit.text().strip(), path])

    def closeEvent(self, event):
        if self._server.isListening():
            self._server.close()
            self._server.deleteLater()
        super(Window, self).closeEvent(event)
コード例 #7
0
class ServerSocket(QObject):
    """Class defining a socket for the server."""

    listening = pyqtSignal(tuple)
    message_received = pyqtSignal(tuple)
    client_disconnected = pyqtSignal(str)

    def __init__(self):
        """Constructor."""
        QObject.__init__(self)

        self.__tcpServer = QTcpServer()

        self.__active_sockets = []

        self.__tcpServer.newConnection.connect(self.__new_connection)

    def __new_connection(self):
        """Method handling a new connection to the server."""
        # Connecting the new client
        client = self.__tcpServer.nextPendingConnection()
        client.readyRead.connect(self.read_message)
        client.disconnected.connect(self.__find_disconnected_client)
        client.disconnected.connect(client.deleteLater)  # Not sure
        self.__active_sockets.append(client)  # Hyper important !!!
        print("A new client connected from address '{}'.".format(
            client.peerAddress().toString()))

    def __find_disconnected_client(self):
        """Method trying to find the disconnected client."""
        self.client_disconnected.emit(self.sender().localAddress().toString())

        self.__active_sockets = []
        for socket in self.__tcpServer.children()[1:]:
            if int(socket.socketDescriptor()) <= 10000:  # Socket is active
                self.__active_sockets.append(socket)

    def get_available_ips(self):
        """Method returning the list of available ips."""
        return QNetworkInterface.allAddresses()

    def listen(self, host=None, port=3000):
        """Method making the server listening to a given address."""
        # If no address was specified: trying to give the best one
        if host is None:
            for ip in self.get_available_ips():
                if ip != QHostAddress.LocalHost and ip.toIPv4Address():
                    host = ip
            if host is None:  # No suitable address was found
                host = QHostAddress.LocalHost
        # The address was given as string
        if type(host) == str:
            host = QHostAddress(host)
        # For printing...
        address = "{}:{}".format(host.toString(), port)
        # Launching server
        if not self.__tcpServer.listen(host, port):
            self.__tcpServer.close()
            print("Unable to listen on address '{}': {}.".format(
                address, self.__tcpServer.errorString()))
            raise ConnectionError(self.__tcpServer.errorString())
        else:
            print("Server is listening on address '{}'.".format(address))
            self.listening.emit((host, port))

    def read_message(self):
        """Method handling the messages."""
        for socket in self.__active_sockets:
            instr = socket.readAll()
            message = str(instr, encoding="utf8")
            if message:
                self.message_received.emit((message, socket))

    def __send_msg(self, message, socket):
        """Method effectively sending a message."""
        socket.write(bytes(message, encoding="utf8"))
        socket.flush()

    def send_message(self, message, recipient=None):
        """Method used to send a message to the clients."""
        if recipient:  # A single recipient was provided
            if type(recipient) is not str:  # Given socket directly
                self.__send_msg(message, recipient)
            else:  # Given ip address
                for socket in self.__active_sockets:
                    if socket.peerAddress().toString() == recipient:
                        self.__send_msg(message, socket)
        else:  # Send for everyone
            for socket in self.__active_sockets:
                self.__send_msg(message, socket)

            # block = QByteArray()
            # out = QDataStream(block, QIODevice.ReadWrite)
            # out.setVersion(QDataStream.Qt_5_0)
            # out.writeUInt16(0)
            # message = bytes(message, encoding="utf8")
            # out.writeString(message)
            # out.device().seek(0)
            # out.writeUInt16(block.size() - 2)
            # socket.write(block)

    def get_address(self):
        """Method returning the adress."""
        return self.__tcpServer.serverAddress()

    def get_port(self):
        """Method returning the port."""
        return self.__tcpServer.serverPort()
コード例 #8
0
class TcpS(QDialog, Ui_TcpServer):
    """
    Class documentation goes here.
    """

    sendFileName = pyqtSignal(str)

    def __init__(self, parent=None):
        """
        Constructor
        
        @param parent reference to the parent widget
        @type QWidget
        """
        super(TcpS, self).__init__(parent)
        self.setupUi(self)
        self.payloadSize = 64 * 1024
        self.totalBytes = 0
        self.bytesWritten = 0
        self.bytesToWrite = 0
        self.theFileName = ""
        self.fileName = ""
        self.localFile = QFile()
        self.outBlock = QByteArray()
        self.time = QTime()
        self.initServer()

    def initServer(self):
        """
        网络设置初始化
        """
        self.tcpPort = 7788
        self.tcpServer = QTcpServer(self)
        self.clientConnection = QTcpSocket(self)
        self.tcpServer.newConnection.connect(self.sendMessage)
        self.serverStatuslabel.setText("请选择要传送的文件")
        self.progressBar.reset()
        self.serverOpenBtn.setEnabled(True)
        self.serverSendBtn.setEnabled(False)
        self.tcpServer.close()

    def refused(self):
        """
        对端拒绝接收文件
        """
        self.tcpServer.close()
        self.serverStatuslabel.setText("对方拒绝接收")

    def closeEvent(self, event):
        """
        关闭事件
        """
        self.on_serverCloseBtn_clicked()

    def sendMessage(self):
        """
        发送文件
        """
        self.serverSendBtn.setEnabled(False)
        self.clientConnection = self.tcpServer.nextPendingConnection()
        self.clientConnection.bytesWritten.connect(self.updateClientProgress)
        self.serverStatuslabel.setText("开始传送文件 {} !".format(self.theFileName))

        self.localFile = QFile(self.fileName)
        if not (self.localFile.open(QFile.ReadOnly)):
            errorMsg = "无法读取文件 {}:\n {}".format(self.fileName,
                                                self.localFile.errorString())
            QMessageBox.warning(self, "应用程序", errorMsg)
            return

        self.serverCloseBtn.setText("取消")

        self.totalBytes = self.localFile.size()  #单位:字节
        sendOut = QDataStream(self.outBlock, QIODevice.WriteOnly)
        sendOut.setVersion(QDataStream.Qt_5_4)
        self.time.start()
        currentFile = self.fileName.split("/")[-1]
        sendOut.writeInt64(0)
        sendOut.writeInt64(0)
        sendOut.writeQString(currentFile)
        self.totalBytes += self.outBlock.size()
        sendOut.device().seek(0)
        sendOut.writeInt64(self.totalBytes)
        sendOut.writeInt64(self.outBlock.size() - 2)
        self.bytesToWrite = self.totalBytes - self.clientConnection.write(
            self.outBlock)
        self.outBlock.resize(0)

    def updateClientProgress(self, numBytes):
        """
        发送进度显示
        """
        qApp.processEvents()
        self.bytesWritten += numBytes
        if self.bytesWritten > 0:
            self.block = self.localFile.read(
                min(self.bytesToWrite, self.payloadSize))
            self.bytesToWrite -= self.clientConnection.write(self.block)
        else:
            self.localFile.close()

        byteSent = self.bytesWritten / (1024 * 1024)
        useTime = self.time.elapsed() / 1000
        speed = self.bytesWritten / useTime / (1024 * 1024)
        total = self.totalBytes / (1024 * 1024)
        left = (total - byteSent) / speed

        if byteSent < 0.01:
            byteSent = self.bytesWritten / 1024
            speed = self.bytesWritten / useTime / 1024
            total = self.totalBytes / 1024
            if left > 0:
                sendInfo = "已发送 {0:.2f}KB({1:.2f}KB/s)\n共{2:.2f}KB 已用时:{3:.1f}秒\n 估计剩余时间:{4:.1f}秒".format(
                    byteSent, speed, total, useTime, left)
            else:
                sendInfo = "已发送 {0:.2f}KB({1:.2f}KB/s)\n共{2:.2f}KB 用时:{3:.1f}秒\n".format(
                    byteSent, speed, total, useTime)
        else:
            if left > 0:
                sendInfo = "已发送 {0:.2f}MB({1:.2f}MB/s)\n共{2:.2f}MB 已用时:{3:.1f}秒\n 估计剩余时间:{4:.1f}秒".format(
                    byteSent, speed, total, useTime, left)
            else:
                sendInfo = "已发送 {0:.2f}MB({1:.2f}MB/s)\n共{2:.2f}MB 用时:{3:.1f}秒\n".format(
                    byteSent, speed, total, useTime)

        self.progressBar.setMaximum(total)
        self.progressBar.setValue(byteSent)

        if self.bytesWritten == self.totalBytes:
            self.serverCloseBtn.setText("关闭")

        self.serverStatuslabel.setText(sendInfo)

    @pyqtSlot()
    def on_serverOpenBtn_clicked(self):
        """
        打开文件
        """
        self.fileName = QFileDialog.getOpenFileName(self, '打开文件', './')[0]
        if self.fileName:
            self.theFileName = self.fileName.split("/")[-1]
            self.serverStatuslabel.setText("要传送的文件为:{}".format(
                self.theFileName))
            self.serverSendBtn.setEnabled(True)
            self.serverOpenBtn.setEnabled(False)

    @pyqtSlot()
    def on_serverSendBtn_clicked(self):
        """
        发送文件
        """
        if not (self.tcpServer.listen(QHostAddress.Any, self.tcpPort)):
            errorMsg = self.tcpServer.errorString()
            QMessageBox.warning(self, "错误", "发送失败:\n {}".format(errorMsg))
            self.TcpServer.close()
            return

        self.serverStatuslabel.setText("等待对方接收... ...")
        self.serverSendBtn.setEnabled(False)
        self.sendFileName.emit(self.theFileName)

    @pyqtSlot()
    def on_serverCloseBtn_clicked(self):
        """
        取消或者关闭
        """
        if self.tcpServer.isListening():
            self.tcpServer.close()
            if self.localFile.isOpen():
                self.localFile.close()
            self.clientConnection.abort()

        if self.serverCloseBtn.text() == "取消":
            self.serverCloseBtn.setText("关闭")
        else:
            self.close()
            self.serverOpenBtn.setEnabled(True)
            self.serverSendBtn.setEnabled(False)
            self.progressBar.reset()
            self.totalBytes = 0
            self.bytesWritten = 0
            self.bytesToWrite = 0
            self.serverStatuslabel.setText("请选择要传送的文件")
コード例 #9
0
class Server(QObject):
    debug = True
    log = sys.stderr
    username = '******'
    password = '******'
    stopServing = pyqtSlot()

    def __init__(self, parent=None):
        super(Server, self).__init__(parent)
        self.proxy_server = QTcpServer(self)
        self.proxy_server.listen(QHostAddress.Any, 8000)
        self.proxy_server.newConnection.connect(self.manage_request)

        if self.debug:
            self.log.write('Server running on localhost port %s\n\n' %
                           self.port())

    def port(self):
        return self.proxy_server.serverPort()

    def addr(self):
        return self.proxy_server.serverAddress().toString()

    def stopServing(self):
        if self.debug:
            self.log.write('Service is stopping...\n\n')

        # does not "close" the server, just stop listening...
        self.proxy_server.close()

        if self.proxy_server.hasPendingConnections():
            socket = self.proxy_server.nextPendingConnection()
            while socket:
                socket.abort()
                socket = self.proxy_server.nextPendingConnection()

    def manage_request(self):
        proxy_server = self.sender()
        # Qt docs says that the caller of nextPendingConnection()
        # is the parent of the socket
        socket = proxy_server.nextPendingConnection()
        socket.readyRead.connect(self.process_request)
        socket.disconnected.connect(socket.deleteLater)

    def authorize_request(self, request_data):
        return True
        header = QHttpRequestHeader(QString(request_data))
        if self.debug:
            self.log.write(header.toString())

        auth = header.value('Proxy-Authorization')
        if not auth:
            return False

        challenge = base64.b64encode(self.username + ':' + self.password)
        return challenge == str(auth).split()[1]

    def process_request(self):
        socket = self.sender()
        request_data = socket.readAll()

        if not self.authorize_request(request_data):
            socket.write('HTTP/1.1 407 Proxy Authentication Required\r\n')
            if self.debug:
                self.log.write('407 Proxy Authentication Required\n\n')
            socket.write('Proxy-Authenticate: Basic realm="test"\r\n')
            socket.write('\r\n')
            socket.disconnectFromHost()
            return
        else:
            # remove Proxy-Authorization header
            start = request_data.indexOf('Proxy-Authorization:')
            end = request_data.lastIndexOf('\r\n')
            request_data.remove(start, end)
            request_data.append('\r\n')

        pos = request_data.indexOf('\r\n')
        request_line = request_data.left(pos)
        request_data.remove(0, pos + 2)

        entries = request_line.split(' ')
        method = entries[0]
        address = entries[1]
        version = entries[2]
        port = '80'

        if address.count(':') > 1:
            protocol, host, port = address.split(':')
        else:
            protocol, host = address.split(':')

        print('address' + str(address))

        #url = QUrl( protocol + host )
        url = QUrl.fromEncoded(address)
        #url.setHost( host )
        #url.setPort( int(port) )

        if not url.isValid():
            if self.debug:
                self.log.write('Invalid URL: %s\n\n', url)
            socket.disconnectFromHost()
            return

        host = url.host()
        port = 80 if (url.port() < 0) else url.port()
        req = url.encodedPath()
        if url.hasQuery():
            req.append('?').append(url.encodedQuery())
        request_line = method + ' ' + req + ' ' + version + '\r\n'
        request_data.prepend(request_line)

        if self.debug:
            self.log.write(method + ' ' + address + ' ' + version + '\n\n')

        key = host + ':' + QString.number(port)
        proxy_socket = socket.findChild(QTcpSocket, key)
        if proxy_socket:
            proxy_socket.setObjectName(key)
            proxy_socket.setProperty('url', url)
            proxy_socket.setProperty('request_data', request_data)
            proxy_socket.write(request_data)
        else:
            proxy_socket = QTcpSocket(socket)
            proxy_socket.setObjectName(key)
            proxy_socket.setProperty('url', url)
            proxy_socket.setProperty('request_data', request_data)
            proxy_socket.connected.connect(self.send_request)
            proxy_socket.readyRead.connect(self.transfer_data)
            proxy_socket.disconnected.connect(self.close_connection)
            proxy_socket.error.connect(self.close_connection)
            proxy_socket.connectToHost(host, port)

    def send_request(self):
        proxy_socket = self.sender()
        request_data = proxy_socket.property('request_data').toByteArray()
        proxy_socket.write(request_data)

    def transfer_data(self):
        proxy_socket = self.sender()
        socket = proxy_socket.parent()
        socket.write(proxy_socket.readAll())

    def close_connection(self):
        proxy_socket = self.sender()
        if proxy_socket:
            socket = proxy_socket.parent()
            if isinstance(socket, QTcpSocket) and socket:
                socket.disconnectFromHost()
            if proxy_socket.error() != QTcpSocket.RemoteHostClosedError:
                url = proxy_socket.property('url').toUrl()
                error_string = proxy_socket.errorString()

                if self.debug:
                    self.log.write('Error for %s %s\n\n' % (url, error_string))

            proxy_socket.deleteLater()
コード例 #10
0
ファイル: tcp.py プロジェクト: alexeynaumov/qnetwork
class TcpServer(QObject):
    '''
    TCP/IP server class.

    Usage:
        import sys
        import tcp
        from PyQt4.QtCore import QCoreApplication
        from PyQt4.QtNetwork import QHostAddress


        def main():
            application = QCoreApplication(sys.argv)

            tcpServer = tcp.TcpServer()

            def onConnected(descriptor):
                print("Client [%s] connected. Now total: %s" % (descriptor, len(tcpServer.descriptors())))
                tcpServer.write(descriptor, "Hello dude")

            def onDisconnected(descriptor):
                print("Client [%s] disconnected. Now total: %s" % (descriptor, len(tcpServer.descriptors())))

            def onError(descriptor, error):
                print("Error [%s]: ", descriptor, error)

            def onRead(descriptor, data):
                print("Read from [%s] %s byte(s): %s" % (descriptor, len(data), data))

            tcpServer.onConnected = onConnected
            tcpServer.onDisconnected = onDisconnected
            tcpServer.onError = onError
            tcpServer.onRead = onRead
            tcpServer.listen(QHostAddress.Any, 9000)

            sys.exit(application.exec_())

        if __name__ == "__main__":
            main()
    '''
    def __init__(self, parent=None):
        QObject.__init__(self, parent)
        self.__server = QTcpServer(parent)
        self.__clients = dict()  # All active clients

        # Callbacks
        self.__on_connected = None
        self.__on_disconnected = None
        self.__on_error = None
        self.__on_read = None

        # Signals and slots connections
        self.__server.newConnection.connect(self.__onNewConnection)

    # Slots
    @pyqtSlot()
    def __onNewConnection(self):
        '''
        The slot is called every time a client connects to the server. The client's socket(QTcpSocket) <socket> and
        descriptor(int) <descriptor> are defined. The socket is appended to the dictionary of connected
        clients(key=client's descriptor, value=client's socket). Then, socket's descriptor is passed to
        __onConnected method.
        :return: None
        '''

        socket = self.__server.nextPendingConnection()
        socket.disconnected.connect(self.__onDisconnected)
        socket.error.connect(self.__onError)
        socket.readyRead.connect(self.__onReadyRead)
        descriptor = id(socket)
        self.__clients[descriptor] = socket
        self.__onConnected(descriptor)

    @pyqtSlot()
    def __onConnected(self, descriptor):
        '''
        The method is called by __onNewConnection every time a client connects to the server. If __on_connected callback
        is set, it is executed with socket's descriptor(int) <descriptor> argument.
        :param descriptor(int): a newly connected client's socket descriptor, the socket itself is in self.__clients
        dictionary(key=client's descriptor, value=client's socket);
        :return: None
        '''

        if self.__on_connected:
            self.__on_connected(descriptor)

    @pyqtSlot()
    def __onDisconnected(self):
        '''
        The slot is called when the connected client disconnects from the server. The client's socket(QTcpSocket)
        <socket> and its descriptor(int) <descriptor> are defined, and then the descriptor is passed to
        __on_disconnected callback.
        :return: None
        '''

        if self.__on_disconnected:
            socket = self.sender()
            descriptor = id(socket)
            self.__clients.pop(descriptor, None)
            self.__on_disconnected(descriptor)

    @pyqtSlot()
    def __onError(self, socketError):
        '''
        The slot is called when an error(PyQt4.QtNetwork.SocketError) <socketError> occurs. The socket's descriptor(int)
        <descriptor> with error code(int) <errorCode> and description(str) <errorDescription> are defined and passed
        to __on_error callback.
        :param error(QAbstractSocket.SocketError): socket error;
        :return: None
        '''

        if self.__on_error:
            socket = self.__server.sender()
            descriptor = id(socket)
            errorCode = int(socketError)
            errorDescription = str(self.__server.errorString())
            error = (errorCode, errorDescription)

            self.__on_error(descriptor, error)

    @pyqtSlot()
    def __onReadyRead(self):
        '''
        The slot is called when new data is available for reading from the client. The client's socket descriptor(int)
        <descriptor> is defined, and all available data(str) <data> is read. Then, the socket descriptor and the data
        are passed to __on_read callback.
        :return: None
        '''

        if self.__on_read:
            socket = self.sender()
            descriptor = id(socket)
            data = socket.readAll().data()
            self.__on_read(descriptor, data)

    # Setters
    def __connected(self, callback):
        self.__on_connected = callback

    def __disconnected(self, callback):
        self.__on_disconnected = callback

    def __error(self, callback):
        self.__on_error = callback

    def __read(self, callback):
        self.__on_read = callback

    # Methods
    def isListening(self):
        '''
        Return True if the server is currently listening for incoming connections, otherwise returns False.
        :return: bool
        '''

        return self.__server.isListening()

    def listen(self, address=None, port=0):
        '''
        Tell the server to listen for incoming connections on address(QHostAddress) <address> and port(int) <port>. If
        port is 0, a port is chosen automatically. If address is QHostAddress.Any, the server will listen on all network
        interfaces.
        :param address(QHosAddress): address to listen to;
        :param port(int): the port to listen to;
        :return: bool, return True on success, otherwise return False
        '''
        self.__server.listen(address, port)

    def socket(self, descriptor):
        '''
        Return socket(QTcpSocket) with the given descriptor(int) <descriptor> or None if it is not found.
        :param descriptor(int): socket descriptor;
        :return: socket(QTcpSocket) or None
        '''

        return self.__clients.get(descriptor, None)

    def descriptors(self):
        '''
        Return all sockets' descriptors available.
        :return list of int
        '''

        return sorted(self.__clients.keys())

    def write(self, descriptor, data):
        '''
        Write data(str) <data> to the client's socket with the given descriptor(int) <descriptor>.
        :param descriptor(int): client's socket descriptor;
        :param data(str), data to be written;
        :return: int, the number of bytes that were actually written, or -1 if an error occurred
        '''

        socket = self.socket(descriptor)
        if socket:
            return socket.write(data)
        else:
            return -1

    def disconnect(self, descriptor):
        '''
        Disconnect the client socket with the given descriptor(int) <descriptor>.
        :param descriptor(int): client's socket descriptor;
        :return: None
        '''

        socket = self.socket(descriptor)
        if socket:
            socket.close()

    def close(self):
        '''
        Close the server.
        :return: None
        '''
        for socket in self.__clients.values():
            socket.close()

        self.__server.close()

    # Properties
    onConnected = property(fset=__connected)
    onDisconnected = property(fset=__disconnected)
    onError = property(fset=__error)
    onRead = property(fset=__read)
コード例 #11
0
def isAvailable(port):
    server = QTcpServer()
    result = server.listen(QHostAddress("127.0.0.1"), port)
    server.close()
    return result
コード例 #12
0
ファイル: loopback.py プロジェクト: death-finger/Scripts
class Dialog(QDialog):
    TotalBytes = 50 * 1024 * 1024
    PayloadSize = 65536

    def __init__(self, parent=None):
        super(Dialog, self).__init__(parent)

        self.tcpServer = QTcpServer()
        self.tcpClient = QTcpSocket()
        self.bytesToWrite = 0
        self.bytesWritten = 0
        self.bytesReceived = 0

        self.clientProgressBar = QProgressBar()
        self.clientStatusLabel = QLabel("Client ready")
        self.serverProgressBar = QProgressBar()
        self.serverStatusLabel = QLabel("Server ready")

        self.startButton = QPushButton("&Start")
        self.quitButton = QPushButton("&Quit")

        buttonBox = QDialogButtonBox()
        buttonBox.addButton(self.startButton, QDialogButtonBox.ActionRole)
        buttonBox.addButton(self.quitButton, QDialogButtonBox.RejectRole)

        self.startButton.clicked.connect(self.start)
        self.quitButton.clicked.connect(self.close)
        self.tcpServer.newConnection.connect(self.acceptConnection)
        self.tcpClient.connected.connect(self.startTransfer)
        self.tcpClient.bytesWritten.connect(self.updateClientProgress)
        self.tcpClient.error.connect(self.displayError)

        mainLayout = QVBoxLayout()
        mainLayout.addWidget(self.clientProgressBar)
        mainLayout.addWidget(self.clientStatusLabel)
        mainLayout.addWidget(self.serverProgressBar)
        mainLayout.addWidget(self.serverStatusLabel)
        mainLayout.addStretch(1)
        mainLayout.addSpacing(10)
        mainLayout.addWidget(buttonBox)
        self.setLayout(mainLayout)

        self.setWindowTitle("Loopback")

    def start(self):
        self.startButton.setEnabled(False)

        QApplication.setOverrideCursor(Qt.WaitCursor)

        self.bytesWritten = 0
        self.bytesReceived = 0

        while not self.tcpServer.isListening() and not self.tcpServer.listen():
            ret = QMessageBox.critical(self, "Loopback",
                    "Unable to start the test: %s." % self.tcpServer.errorString(),
                    QMessageBox.Retry | QMessageBox.Cancel)
            if ret == QMessageBox.Cancel:
                return

        self.serverStatusLabel.setText("Listening")
        self.clientStatusLabel.setText("Connecting")

        self.tcpClient.connectToHost(QHostAddress(QHostAddress.LocalHost), self.tcpServer.serverPort())

    def acceptConnection(self):
        self.tcpServerConnection = self.tcpServer.nextPendingConnection()
        self.tcpServerConnection.readyRead.connect(self.updateServerProgress)
        self.tcpServerConnection.error.connect(self.displayError)

        self.serverStatusLabel.setText("Accepted connection")
        self.tcpServer.close()

    def startTransfer(self):
        self.bytesToWrite = Dialog.TotalBytes - self.tcpClient.write(QByteArray(Dialog.PayloadSize, '@'))
        self.clientStatusLabel.setText("Connected")

    def updateServerProgress(self):
        self.bytesReceived += self.tcpServerConnection.bytesAvailable()
        self.tcpServerConnection.readAll()

        self.serverProgressBar.setMaximum(Dialog.TotalBytes)
        self.serverProgressBar.setValue(self.bytesReceived)
        self.serverStatusLabel.setText("Received %dMB" % (self.bytesReceived / (1024 * 1024)))

        if self.bytesReceived == Dialog.TotalBytes:
            self.tcpServerConnection.close()
            self.startButton.setEnabled(True)
            QApplication.restoreOverrideCursor()

    def updateClientProgress(self, numBytes):
        self.bytesWritten += numBytes
        if self.bytesToWrite > 0:
            self.bytesToWrite -= self.tcpClient.write(QByteArray(
                                        min(self.bytesToWrite, Dialog.PayloadSize), '@'))

        self.clientProgressBar.setMaximum(Dialog.TotalBytes)
        self.clientProgressBar.setValue(self.bytesWritten)
        self.clientStatusLabel.setText("Sent %dMB" % (self.bytesWritten / (1024 * 1024)))

    def displayError(self, socketError):
        if socketError == QTcpSocket.RemoteHostClosedError:
            return

        QMessageBox.information(self, "Network error",
                "The following error occured: %s." % self.tcpClient.errorString())

        self.tcpClient.close()
        self.tcpServer.close()
        self.clientProgressBar.reset()
        self.serverProgressBar.reset()
        self.clientStatusLabel.setText("Client ready")
        self.serverStatusLabel.setText("Server ready")
        self.startButton.setEnabled(True)
        QApplication.restoreOverrideCursor()
コード例 #13
0
class Dialog(QDialog):
    def __init__(self, parent: QWidget = None) -> None:
        super().__init__(parent)

        self.tcpServer = QTcpServer()
        self.tcpClient = QTcpSocket()
        self.tcpServerConnection: QTcpSocket = None

        self.bytesToWrite = 0
        self.bytesWritten = 0
        self.bytesReceived = 0

        self.clientProgressBar = QProgressBar()
        self.clientStatusLabel = QLabel(self.tr("Client ready"))
        self.serverProgressBar = QProgressBar()
        self.serverStatusLabel = QLabel(self.tr("Server ready"))

        self.startButton = QPushButton(self.tr("&Start"))
        self.quitButton = QPushButton(self.tr("&Quit"))

        self.buttonBox = QDialogButtonBox()
        self.buttonBox.addButton(self.startButton, QDialogButtonBox.ActionRole)
        self.buttonBox.addButton(self.quitButton, QDialogButtonBox.RejectRole)

        self.startButton.clicked.connect(self.start)
        self.quitButton.clicked.connect(self.close)
        self.tcpServer.newConnection.connect(self.acceptConnection)
        self.tcpClient.connected.connect(self.startTransfer)
        self.tcpClient.bytesWritten.connect(self.updateClientProgress)
        self.tcpClient.error.connect(self.displayError)

        mainLayout = QVBoxLayout(self)
        mainLayout.addWidget(self.clientProgressBar)
        mainLayout.addWidget(self.clientStatusLabel)
        mainLayout.addWidget(self.serverProgressBar)
        mainLayout.addWidget(self.serverStatusLabel)
        mainLayout.addStretch(1)
        mainLayout.addSpacing(10)
        mainLayout.addWidget(self.buttonBox)

    @pyqtSlot()
    def start(self):
        self.startButton.setEnabled(False)

        QGuiApplication.setOverrideCursor(Qt.WaitCursor)

        self.bytesWritten = 0
        self.bytesReceived = 0

        while not self.tcpServer.isListening() and not self.tcpServer.listen():
            ret = QMessageBox.critical(
                self,
                self.tr("Loopback"),
                self.tr(
                    "Unable to start the test: %s" % (self.tcpServer.errorString())
                ),
                QMessageBox.Retry | QMessageBox.Cancel,
            )
            if ret == QMessageBox.Cancel:
                return

        self.serverStatusLabel.setText(self.tr("Listening"))
        self.clientStatusLabel.setText(self.tr("Connecting"))
        self.tcpClient.connectToHost(
            QHostAddress.LocalHost, self.tcpServer.serverPort()
        )

    @pyqtSlot()
    def acceptConnection(self):
        self.tcpServerConnection = self.tcpServer.nextPendingConnection()
        if not self.tcpServerConnection:
            self.serverStatusLabel.setText(
                self.tr("Error: got invalid pending connection!")
            )
            return

        self.tcpServerConnection.readyRead.connect(self.updateServerProgress)
        self.tcpServerConnection.error.connect(self.displayError)
        self.tcpServerConnection.disconnected.connect(
            self.tcpServerConnection.deleteLater
        )

        self.serverStatusLabel.setText(self.tr("Accepted connection"))
        self.tcpServer.close()

    @pyqtSlot()
    def startTransfer(self):
        # called when the TCP client connected to the loopback server
        self.bytesToWrite = TOTAL_BYTES - int(
            self.tcpClient.write(QByteArray(PAYLOAD_SIZE, "@"))
        )
        self.clientStatusLabel.setText(self.tr("Connected"))

    @pyqtSlot()
    def updateServerProgress(self):
        self.bytesReceived += int(self.tcpServerConnection.bytesAvailable())
        self.tcpServerConnection.readAll()

        self.serverProgressBar.setMaximum(TOTAL_BYTES)
        self.serverProgressBar.setValue(self.bytesReceived)
        self.serverStatusLabel.setText(
            self.tr("Received %dMB" % (self.bytesReceived / (1024 * 1024),))
        )

        if self.bytesReceived == TOTAL_BYTES:
            self.tcpServerConnection.close()
            self.startButton.setEnabled(True)

            QGuiApplication.restoreOverrideCursor()

    @pyqtSlot("qint64")
    def updateClientProgress(self, numBytes):
        self.bytesWritten += int(numBytes)

        if self.bytesToWrite > 0 and self.tcpClient.bytesToWrite() <= 4 * PAYLOAD_SIZE:
            self.bytesToWrite -= self.tcpClient.write(
                QByteArray(min(self.bytesToWrite, PAYLOAD_SIZE), "@")
            )

        self.clientProgressBar.setMaximum(TOTAL_BYTES)
        self.clientProgressBar.setValue(self.bytesWritten)
        self.clientStatusLabel.setText(
            self.tr("Sent %dMB" % (self.bytesWritten / (1024 * 1024),))
        )

    @pyqtSlot(QAbstractSocket.SocketError)
    def displayError(self, socketError):
        if socketError == QTcpSocket.RemoteHostClosedError:
            return

        QMessageBox.information(
            self,
            self.tr("Network error"),
            self.tr(
                "The following error occurred: %s." % (self.tcpClient.errorString(),)
            ),
        )
        self.tcpClient.close()
        self.tcpServer.close()
        self.clientProgressBar.reset()
        self.serverProgressBar.reset()
        self.clientStatusLabel.setText(self.tr("Client ready"))
        self.serverStatusLabel.setText(self.tr("Server ready"))
        self.startButton.setEnabled(True)
        QGuiApplication.restoreOverrideCursor()
コード例 #14
0
class ListenPipe(QObject):
    sig_data_arrived = pyqtSignal(QByteArray)
    sig_listening_state = pyqtSignal(bool)

    def __init__(self, parent=None):
        super(ListenPipe, self).__init__(parent=parent)

        self.tcpServer = QTcpServer()
        self.socketClients = []

        self.tcpServer.newConnection.connect(self.on_newconnection)

    @pyqtSlot()
    def start_listen(self):
        print('start_listen:%s %s' % (appsetting.listen_ip, appsetting.listen_port))
        self.tcpServer.close()
        for socketClient in self.socketClients:
            socketClient.close()
            socketClient.deleteLater()

        if appsetting.listen_enable != '0':
            self.tcpServer.listen(QHostAddress(appsetting.listen_ip), int(appsetting.listen_port))

        self.sig_listening_state.emit(self.tcpServer.isListening())

    @pyqtSlot()
    def on_newconnection(self):
        print('on_newconnection')
        socketClient = self.tcpServer.nextPendingConnection()
        socketClient.readyRead.connect(self.on_readyRead)
        socketClient.connected.connect(self.on_connected)
        socketClient.disconnected.connect(self.on_disconnected)
        socketClient.error.connect(self.on_error)
        self.socketClients.append(socketClient)
        print('self.socketClients size=%d' % len(self.socketClients))

    @pyqtSlot()
    def on_readyRead(self):
        print("%s on_readyRead" % self.__class__.__name__)
        socketClient = self.sender()
        data = socketClient.readAll()
        #print(data)
        self.sig_data_arrived.emit(data)

    @pyqtSlot(QByteArray)
    def on_data_arrived(self, data):
        print("%s on_data_arrived" % self.__class__.__name__)
        for socketClient in self.socketClients:
            socketClient.write(data)

    @pyqtSlot()
    def on_connected(self):
        print('on_connected')

    @pyqtSlot()
    def on_disconnected(self):
        print('on_disconnected')
        socketClient = self.sender()
        self.socketClients.remove(socketClient)
        socketClient.deleteLater()
        print('self.socketClients size=%d' % len(self.socketClients))

    @pyqtSlot()
    def on_error(self):
        socketClient = self.sender()
        print('%s on_error:%s' % (self.__class__.__name__, socketClient.errorString()))