Reputation: 159
I would like to write a simpe program that can handle a server-client connection (1:1 connection is enough) in PyQt. I was able to write the socket part but with the GUI I have no idea. I just want to have 2 dialogs one for the server and one for the client(very simple, only 1 button for sending and a textfield to type the message). I want to send a message from the server to the client and then reply to server with another message. Do you have any idea how to begin? Or maybe a sample code? Thank you
Code:
The GUI was created by the Desginer.
from PyQt5 import QtCore, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(353, 266)
self.label = QtWidgets.QLabel(Dialog)
self.label.setGeometry(QtCore.QRect(20, 30, 47, 13))
self.label.setObjectName("label")
self.pushButton = QtWidgets.QPushButton(Dialog)
self.pushButton.setGeometry(QtCore.QRect(80, 110, 75, 23))
self.pushButton.setObjectName("pushButton")
self.textEdit = QtWidgets.QTextEdit(Dialog)
self.textEdit.setGeometry(QtCore.QRect(80, 20, 141, 71))
self.textEdit.setObjectName("textEdit")
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.label.setText(_translate("Dialog", "Message:"))
self.pushButton.setText(_translate("Dialog", "Send"))
This the Dialog class:
class Dialog(QDialog, Ui_Dialog):
def __init__(self,socket):
super(Dialog, self).__init__()
self.setupUi(self)
self.socket = socket
def send(self):
message = self.textEdit.toPlainText()
self.socket.send(message.encode())
Server class:
class Server():
def __init__(self):
host = socket.gethostname()
port = 5000
server_socket = socket.socket()
server_socket.bind((host, port))
server_socket.listen(2)
conn, address = server_socket.accept()
print("Connection from: " + str(address))
gui = Dialog(server_socket)
gui.show()
while True:
data = conn.recv(1024).decode()
if not data:
break
print("message: " + str(data))
conn.close()
if __name__ == '__main__':
server = Server()
Client class:
class Client():
def __init__(self):
host = socket.gethostname()
port = 5000
client_socket = socket.socket()
client_socket.connect((host, port))
gui = Dialog(client_socket)
gui.show()
message = ""
while message.lower().strip() != 'bye':
data = client_socket.recv(1024).decode()
print('message: ', data)
client_socket.close()
if __name__ == '__main__':
client = Client()
Upvotes: 2
Views: 9847
Reputation: 3731
To keep a few things simple:
The resultant of your question is spending a lot of coding time (approx. 2-3 hours). Thus a tiny walk-through to get you on the right path again to do the next few steps yourself.
main
program file in this case is Dialog.py and not Client.py.Dialog
will be an executable.rename Client.py into LOGIN_GUI
or something that refers to its function of "local login" because that is what you try to accomplish. Use name client.py for remote logging (different GUI than server!).
3.In Dialog use pythons multiprocessing
.
3a. Process 1 runs main app
;
3b. Process 2 runs client-server;
3c. Outsource other tasks taking more than 1-2sec (shows as "freezing" in main GUI).
Dialog.py => MyMainAppNameisNOtDialog.py (avoid confusion/typo's inside your scripting code)
If you code your server ThreadingMixIn
style like below you are able to log-in from two different computers. This is as far as I know not available as tool in pyqt5. See also inline comments inside the below code.
Server-side (modification of pythons Socket-server ThreadingMixIn):
import socket
import threading
import SocketServer
# MyAwesomelyNamedServerScript.py
class ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler):
def handle(self):
def func1(scr1):
#put code that does something here.
print 'func1 : %s' % scr1
return scr1
def funct2(scr2):
#put code that does something here.
print 'func2 : %s' % scr2
return scr2
# self.request is the TCP socket connected to the client
cur_thread = threading.current_thread()
data = self.request.recv(1024)
# In the data package the IP from client.
# Extract and add to an IP list (e.g. max 2 connection.)
# if/else statement: if max connection reached than report back "cannot connect... waiting in queue or something".
# limiting the request also prevent DDos attacks from the start.
data_proc = func1(data) # do something once
data = func2(data_proc) # do something twice
response = "{}: {}".format(cur_thread.name, data)
self.request.sendall(response)
class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
pass
def setupServer(ip = None, port = None, message = None):
# Ip, port, message can be linked to below code if you want exernal input via GUI
# Port 0 means to select an arbitrary unused port
HOST, PORT = "localhost", 0
server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
ip, port = server.server_address
# Start a thread with the server -- that thread will then start one
# more thread for each request
server_thread = threading.Thread(target=server.serve_forever)
# Exit the server thread when the main thread terminates
server_thread.daemon = True
server_thread.start()
print "Server loop running in thread:", server_thread.name
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((ip, port))
try:
sock.sendall(message)
response = sock.recv(1024)
print "Received: {}".format(response)
finally:
sock.close()
def test_main():
#client(ip, port, "Hello World 1")
#client(ip, port, "Hello World 2")
#client(ip, port, "Hello World 3")
client(message = "Hello World 1")
client(message = "Hello World 2")
client(message = "Hello World 3")
server.shutdown()
server.server_close()
if __name__ == "__main__":
test_main() #runs the main test
The MainApp.py script in short:
import myloginscript
import myAwesomeMainGUI
...snippet ... <incl. Qt imports, etc.> ...
#MainApp.py
class MyMainUI(QtWidgets.QMainWindow, myAwesomeMainGUI.Ui_MainWindow):
...snippet <your code>...
def setUpass(self, username):
# do whatever you want with the username
# if Pword brought here then login.username.text() needs to be altered to get pw instead.
self.username = username # this variable shoud be made inside your main code.
# self.label.setText("Username: %s" % self.username)
print 'The username is : %s' % self.username
if _name__ = '__main__':
app.QApplication(sys.argv)
login= myloginscript() # this runs your login script (GUI starts if attached therein.)
if login.exec():
window = MymainwindowDialog() # main appwindow...not login GUI.
window.setUpass(login.username.text())
window.show()
sys.stdout.flush()
try:
sys.exit(app.exec())
except:
print('Exit now.. wrong Uname or Pword')
else:
sys.exit(-1) # user pressed 'Cancel', lets quit the program here.
Upvotes: 4