1#!/usr/bin/env python 2 3 4############################################################################# 5## 6## Copyright (C) 2013 Riverbank Computing Limited. 7## Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 8## All rights reserved. 9## 10## This file is part of the examples of PyQt. 11## 12## $QT_BEGIN_LICENSE:BSD$ 13## You may use this file under the terms of the BSD license as follows: 14## 15## "Redistribution and use in source and binary forms, with or without 16## modification, are permitted provided that the following conditions are 17## met: 18## * Redistributions of source code must retain the above copyright 19## notice, this list of conditions and the following disclaimer. 20## * Redistributions in binary form must reproduce the above copyright 21## notice, this list of conditions and the following disclaimer in 22## the documentation and/or other materials provided with the 23## distribution. 24## * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor 25## the names of its contributors may be used to endorse or promote 26## products derived from this software without specific prior written 27## permission. 28## 29## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 30## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 31## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 32## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 33## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 34## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 35## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 39## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 40## $QT_END_LICENSE$ 41## 42############################################################################# 43 44 45from PyQt5.QtCore import QByteArray, Qt 46from PyQt5.QtWidgets import (QApplication, QDialog, QDialogButtonBox, QLabel, 47 QMessageBox, QProgressBar, QPushButton, QVBoxLayout) 48from PyQt5.QtNetwork import QHostAddress, QTcpServer, QTcpSocket 49 50 51class Dialog(QDialog): 52 TotalBytes = 50 * 1024 * 1024 53 PayloadSize = 65536 54 55 def __init__(self, parent=None): 56 super(Dialog, self).__init__(parent) 57 58 self.tcpServer = QTcpServer() 59 self.tcpClient = QTcpSocket() 60 self.bytesToWrite = 0 61 self.bytesWritten = 0 62 self.bytesReceived = 0 63 64 self.clientProgressBar = QProgressBar() 65 self.clientStatusLabel = QLabel("Client ready") 66 self.serverProgressBar = QProgressBar() 67 self.serverStatusLabel = QLabel("Server ready") 68 69 self.startButton = QPushButton("&Start") 70 self.quitButton = QPushButton("&Quit") 71 72 buttonBox = QDialogButtonBox() 73 buttonBox.addButton(self.startButton, QDialogButtonBox.ActionRole) 74 buttonBox.addButton(self.quitButton, QDialogButtonBox.RejectRole) 75 76 self.startButton.clicked.connect(self.start) 77 self.quitButton.clicked.connect(self.close) 78 self.tcpServer.newConnection.connect(self.acceptConnection) 79 self.tcpClient.connected.connect(self.startTransfer) 80 self.tcpClient.bytesWritten.connect(self.updateClientProgress) 81 self.tcpClient.error.connect(self.displayError) 82 83 mainLayout = QVBoxLayout() 84 mainLayout.addWidget(self.clientProgressBar) 85 mainLayout.addWidget(self.clientStatusLabel) 86 mainLayout.addWidget(self.serverProgressBar) 87 mainLayout.addWidget(self.serverStatusLabel) 88 mainLayout.addStretch(1) 89 mainLayout.addSpacing(10) 90 mainLayout.addWidget(buttonBox) 91 self.setLayout(mainLayout) 92 93 self.setWindowTitle("Loopback") 94 95 def start(self): 96 self.startButton.setEnabled(False) 97 98 QApplication.setOverrideCursor(Qt.WaitCursor) 99 100 self.bytesWritten = 0 101 self.bytesReceived = 0 102 103 while not self.tcpServer.isListening() and not self.tcpServer.listen(): 104 ret = QMessageBox.critical(self, "Loopback", 105 "Unable to start the test: %s." % self.tcpServer.errorString(), 106 QMessageBox.Retry | QMessageBox.Cancel) 107 if ret == QMessageBox.Cancel: 108 return 109 110 self.serverStatusLabel.setText("Listening") 111 self.clientStatusLabel.setText("Connecting") 112 113 self.tcpClient.connectToHost(QHostAddress(QHostAddress.LocalHost), self.tcpServer.serverPort()) 114 115 def acceptConnection(self): 116 self.tcpServerConnection = self.tcpServer.nextPendingConnection() 117 self.tcpServerConnection.readyRead.connect(self.updateServerProgress) 118 self.tcpServerConnection.error.connect(self.displayError) 119 120 self.serverStatusLabel.setText("Accepted connection") 121 self.tcpServer.close() 122 123 def startTransfer(self): 124 self.bytesToWrite = Dialog.TotalBytes - self.tcpClient.write(QByteArray(Dialog.PayloadSize, '@')) 125 self.clientStatusLabel.setText("Connected") 126 127 def updateServerProgress(self): 128 self.bytesReceived += self.tcpServerConnection.bytesAvailable() 129 self.tcpServerConnection.readAll() 130 131 self.serverProgressBar.setMaximum(Dialog.TotalBytes) 132 self.serverProgressBar.setValue(self.bytesReceived) 133 self.serverStatusLabel.setText("Received %dMB" % (self.bytesReceived / (1024 * 1024))) 134 135 if self.bytesReceived == Dialog.TotalBytes: 136 self.tcpServerConnection.close() 137 self.startButton.setEnabled(True) 138 QApplication.restoreOverrideCursor() 139 140 def updateClientProgress(self, numBytes): 141 self.bytesWritten += numBytes 142 if self.bytesToWrite > 0: 143 self.bytesToWrite -= self.tcpClient.write(QByteArray( 144 min(self.bytesToWrite, Dialog.PayloadSize), '@')) 145 146 self.clientProgressBar.setMaximum(Dialog.TotalBytes) 147 self.clientProgressBar.setValue(self.bytesWritten) 148 self.clientStatusLabel.setText("Sent %dMB" % (self.bytesWritten / (1024 * 1024))) 149 150 def displayError(self, socketError): 151 if socketError == QTcpSocket.RemoteHostClosedError: 152 return 153 154 QMessageBox.information(self, "Network error", 155 "The following error occured: %s." % self.tcpClient.errorString()) 156 157 self.tcpClient.close() 158 self.tcpServer.close() 159 self.clientProgressBar.reset() 160 self.serverProgressBar.reset() 161 self.clientStatusLabel.setText("Client ready") 162 self.serverStatusLabel.setText("Server ready") 163 self.startButton.setEnabled(True) 164 QApplication.restoreOverrideCursor() 165 166 167if __name__ == '__main__': 168 169 import sys 170 171 app = QApplication(sys.argv) 172 dialog = Dialog() 173 dialog.show() 174 sys.exit(dialog.exec_()) 175