我想用 PyQt 编写一个简单的程序来处理服务器-客户端连接(1:1 连接就足够了)。我能够编写套接字部分,但是对于 GUI 我不知道。 我只想有 2 个对话框,一个用于服务器,一个用于客户端(非常简单,只有 1 个用于发送的按钮和一个用于键入消息的文本字段)。我想从服务器向客户端发送一条消息,然后用另一条消息回复服务器。 你知道如何开始吗?或者可能是示例代码? 谢谢
代码:
GUI 由设计师创建。
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"))
这是对话框类:
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())
服务器类:
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()
客户端类:
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()
最佳答案
为了简单起见:
你的问题的结果是花费了大量的编码时间(大约 2-3 小时)。因此,一个小小的演练可以让您再次走上正确的道路,自己完成接下来的几个步骤。
- 在这种情况下,您的
main
程序文件是 Dialog.py 而不是 Client.py。 - 如果您构建/编译您的程序,则 Client.py 是 client.pyd 或其他形式的库。在 Windows 上,
Dialog
将是一个可执行文件。 将 Client.py 重命名为
LOGIN_GUI
或引用其“本地登录”功能的名称,因为这是您要实现的目标。使用名称 client.py 进行远程日志记录(与服务器不同的 GUI!)。 3.在对话框中使用pythonsmultiprocessing
。3a。进程 1 运行
main app
;3b。进程 2 运行客户端-服务器;
3c。外包其他耗时超过 1-2 秒的任务(在主 GUI 中显示为“卡住”)。
Dialog.py => MyMainAppNameisNOtDialog.py(避免脚本代码中的混淆/拼写错误)
如果您像下面那样编写服务器 ThreadingMixIn
样式,您就可以从两台不同的计算机登录。据我所知,这是 pyqt5 中不可用的工具。另请参阅以下代码中的内联注释。
服务器端(修改 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
简短的 MainApp.py 脚本:
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.
关于python - PyQt 中的服务器-客户端连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48499713/