这里的快速问题...(顺便说一句,对不起,如果已经得到回答...)我有一个QDialog窗口(由QMainWindow创建),在其中创建和使用了一个套接字。经过一些操作后,QDialog窗口关闭(通过使用QDialog.accept()
命令),然后打开另一个新的QDialog窗口(通过QMainWindow)。从这个新窗口,我希望能够使用已经打开的套接字将信息发送到服务器。
我尝试通过使用以下几行代码来做到这一点:
server = "192.168.100.195"
port = 5555
address = (server, port)
# ----- Some other stuff... ----
socket_de_connexion = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Not using the socket.connect() because the previous QDialog already connected to the server
然后,当我尝试发送邮件时,出现以下错误:
OSError: [ErrnOSError: [Errno 57] Socket is not connected
但是服务器在控制台中向我显示,仍在打开先前在QDialog中创建的套接字(我没有故意关闭它,因为我想继续在程序的多个窗口中使用它。)
有没有办法重用已经打开的套接字通过多个窗口?
顺便说一句,我程序中的每个窗口在单独的文件中都有代码。
编辑:
这里有一些其他信息可以帮助您:
我的第一个QDialog的代码:
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import QRegExpValidator
import socket
import pickle
import sys
server = "192.168.100.195"
port = 5555
class Verification(QDialog):
def __init__(self):
super(Verification, self).__init__()
self.boite_texte_code = QLineEdit(self)
self.bouton_verifier = QPushButton(self)
self.bouton_annuler2 = QPushButton(self)
self.invite_code = QLabel(self)
self.accept_local_test = "Ok"
self.regex2 = QRegExp()
self.validator2 = QRegExpValidator()
self.msg = QMessageBox()
self.socket_de_connexion = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.init_ui()
def init_ui(self):
address = (server, port)
self.socket_de_connexion.connect(address)
# print(self.socket_connexion)
self.resize(290, 110)
self.center()
self.setWindowTitle("Veuillez saisir le code d'invitation:")
self.regex2 = QRegExp("^[0-9]{4}")
self.validator2 = QRegExpValidator(self.regex2)
self.boite_texte_code.setValidator(self.validator2)
self.boite_texte_code.setGeometry(150, 20, 100, 25)
self.bouton_annuler2.setText("Annuler")
self.bouton_annuler2.setGeometry(157, 60, 100, 40)
self.bouton_annuler2.clicked.connect(self.annuler2)
self.bouton_verifier.setDefault(True)
self.bouton_verifier.setEnabled(False)
self.bouton_verifier.setText("Confirmer")
self.bouton_verifier.setGeometry(57, 60, 100, 40)
self.bouton_verifier.clicked.connect(self.confirmer2)
self.invite_code.setText("Code d'invitation:")
self.invite_code.adjustSize()
self.invite_code.move(30, 25)
self.boite_texte_code.textChanged.connect(self.texte_change)
def center(self):
# SOME OTHER CODE NOT NEEDED FOR THIS QUESTION
def annuler2(self):
self.socket_de_connexion.close()
self.close()
def confirmer2(self):
print("Trying to send informations to server...")
msg = self.socket_de_connexion.recv(2048)
message = pickle.loads(msg)
print(message)
if message == "Connecté!":
print("in...")
data_to_send = pickle.dumps("join")
self.socket_de_connexion.send(data_to_send)
verif_pickled = self.socket_de_connexion.recv(2048)
verif = pickle.loads(verif_pickled)
if verif == "code?":
print("asked")
code_to_send = pickle.dumps(self.boite_texte_code.text())
self.socket_de_connexion.send(code_to_send)
answer_pickled = self.socket_de_connexion.recv(2048)
answer = pickle.loads(answer_pickled)
print(answer)
if answer == "No":
print("Oups!")
self.msg.setIcon(QMessageBox.Critical)
self.msg.setText("Erreur! Le code est invalide!")
self.msg.setInformativeText(
"Veuillez vérifier la validité du code. Le programme va maintenant quitter.")
self.msg.setWindowTitle("Oups!")
self.msg.setStandardButtons(QMessageBox.Ok)
self.msg.exec_()
# add msg box here
# self.close()
# socket_de_connexion.shutdown()
# socket_de_connexion.close()
sys.exit()
elif answer == "Yes":
print("yes")
#return self.socket_de_connexion
self.accept()
if self.accept_local_test == "Ok":
if self.boite_texte_code.text() != "":
pass
# self.accept()
else:
print("Nope!")
def texte_change(self):
# SOME OTHER CODE NOT NEEDED FOR THIS QUESTION
if __name__ == '__main__':
app = QDialog()
verification = Verification()
verification.show()
app.exec_()
这是我在另一个文件中的第二个QDialog:
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import jeu
import socket
import pickle
server = "192.168.100.195"
port = 5555
address = (server, port)
class JoinPartie(QDialog):
def __init__(self):
super(JoinPartie, self).__init__()
self.socket_de_connexion = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.une_partie = None
self.code = int
self.setWindowTitle("Veuillez remplir les éléments suivants")
self.boite_texte_username = QLineEdit(self)
self.regex = QRegExp("^\w[\w|\s|\.]+")
self.validator = QRegExpValidator(self.regex)
self.boite_texte_username.setValidator(self.validator)
self.bouton_creer = QPushButton(self)
self.bouton_annuler = QPushButton(self)
self.invite_username = QLabel(self)
self.invite_couleur = QLabel(self)
self.choix_de_couleur = QComboBox(self)
self.init_ui()
def init_ui(self):
# --------------- Paramètres de la fenêtre --------------------
self.resize(640, 325)
self.center()
self.invite_username.setText("Nom d'utilisateur à afficher durant la partie: ")
self.invite_couleur.setText("Veuillez choisir une couleur:")
self.invite_username.adjustSize()
self.invite_couleur.adjustSize()
self.invite_username.move(30, 75)
self.invite_couleur.move(30, 120)
self.boite_texte_username.setGeometry(300, 70, 300, 25)
self.bouton_annuler.setText("Annuler")
self.bouton_annuler.setGeometry(530, 275, 100, 40)
self.bouton_annuler.clicked.connect(self.annuler)
self.bouton_creer.setDefault(True)
self.bouton_creer.setText("Confirmer")
self.bouton_creer.setGeometry(430, 275, 100, 40)
self.bouton_creer.setEnabled(False)
self.bouton_creer.clicked.connect(self.confirmer)
self.choix_de_couleur.setGeometry(307, 115, 300, 25)
self.choix_de_couleur.addItems(["Couleur 1", "Couleur 2", "Couleur 3"])
self.boite_texte_username.textChanged.connect(self.texte_change)
def texte_change(self):
# SOME CODE NOT NEEDED FOR THIS QUESTION
def center(self):
# SOME CODE NOT NEEDED FOR THIS QUESTION
def annuler(self):
self.close()
def confirmer(self):
test = pickle.dumps("test'")
self.socket_de_connexion.send(test) # --> HERE IT FAILS TO SEND, GIVING ME THE ERROR MESSAGE MENTIONNED ABOVE
self.accept()
if not self.isVisible():
self.une_partie = jeu.Jeu(2, self.boite_texte_username.text(), self.choix_de_couleur.currentText())
self.une_partie.show()
if __name__ == '__main__':
app = QDialog()
join_partie = JoinPartie()
join_partie.show()
app.exec_()
这是服务器端的代码:
import socket
import pickle
import random
from _thread import *
games = {}
couleurs = ["Bleu", "Rouge", "Jaune", "Vert"]
paquet_de_carte_initial = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
"SB", "SB", "SB", "SB", "SB", "SB", "SB", "SB", "SB", "SB", "SB", "SB"]
server = "192.168.100.195"
port = 5555
socket_de_connexion = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def code_invitation():
print("")
digit1 = random.choice('0123456789') # Chooses a random element
digit2 = random.choice('0123456789')
digit3 = random.choice('0123456789')
digit4 = random.choice('0123456789')
code = digit1 + digit2 + digit3 + digit4
games[code] = {}
print(games)
return code
def split_cards(nbre):
print("in")
random.shuffle(paquet_de_carte_initial)
random.shuffle(paquet_de_carte_initial)
random.shuffle(paquet_de_carte_initial)
print(paquet_de_carte_initial)
if nbre == 2:
print(2)
player0 = []
player1 = []
main0 = []
main1 = []
for i in range(30):
player0.append(paquet_de_carte_initial[0])
paquet_de_carte_initial.pop(0)
player1.append(paquet_de_carte_initial[0])
paquet_de_carte_initial.pop(0)
# print(player0)
# print(player1)
for j in range(5):
main0.append(paquet_de_carte_initial[0])
paquet_de_carte_initial.pop(0)
main1.append(paquet_de_carte_initial[0])
paquet_de_carte_initial.pop(0)
# print(main0)
# print(main1)
# print(paquet_de_carte_initial)
setup = (player0, main0, player1, main1, paquet_de_carte_initial)
return setup
try:
socket_de_connexion.bind((server, port))
except socket.error as e:
str(e)
socket_de_connexion.listen(4)
print("Le server a démaré. \n En attente d'une connexion...")
def threaded_client(conn):
msg = pickle.dumps("Connecté!")
conn.send(msg)
while True:
try:
data_recu = conn.recv(2048)
data = pickle.loads(data_recu)
print(data)
if data == "create":
print("création d'un code d'invitation...")
code_cree = code_invitation()
print(code_cree)
code_pickled = pickle.dumps(code_cree)
conn.send(code_pickled)
joueurs = conn.recv(2048)
info_joueurs = pickle.loads(joueurs)
print(info_joueurs)
(nbre_de_joueurs, joueur0) = info_joueurs
if nbre_de_joueurs == 2:
cle = str(code_cree)
# games[cle] = {"0": joueur0}
# test = games[cle]["0"]
setup = split_cards(nbre_de_joueurs)
(deck_joueur0, main_joueur0, deck_joueur1, main_joueur1, talon) = setup
joueur0['deck_joueur'] = deck_joueur0
joueur0['main_joueur'] = main_joueur0
print(joueur0)
joueur1 = {'username': '', 'couleur': ''}
joueur1['deck_joueur'] = deck_joueur1
joueur1['main_joueur'] = main_joueur0
joueur0['defausse0'] = []
joueur0['defausse1'] = []
joueur0['defausse2'] = []
joueur0['defausse3'] = []
joueur1['defausse0'] = []
joueur1['defausse1'] = []
joueur1['defausse2'] = []
joueur1['defausse3'] = []
joueur0['count'] = 30
joueur1['count'] = 30
# games[cle] = {"0": joueur0}
# games[cle] = {"1": joueur1}
games[cle] = {"talon": talon}
games[cle]['0'] = joueur0
games[cle]['1'] = joueur1
print(games[cle])
couleurs_restantes = couleurs
couleurs_restantes.remove(joueur0['couleur'])
print(couleurs_restantes)
test = games[cle]['1']['main_joueur']
print(len(test))
to_send_to_j0 = (
games[cle]["talon"], games[cle]['0']['deck_joueur'], games[cle]['0']['main_joueur'],
games[cle]['0']['count'], games[cle]['1']['deck_joueur'][0], len(test), games[cle]['1']['count'])
print(to_send_to_j0)
depart = pickle.dumps(to_send_to_j0)
conn.send(depart)
elif data == "join":
print("in")
ask = pickle.dumps("code?")
conn.send(ask)
code_recu_pickled = conn.recv(2048)
code_recu = pickle.loads(code_recu_pickled)
print(code_recu)
verif = games.get(str(code_recu))
if verif is not None:
print("yes")
reponse = pickle.dumps("Yes")
conn.send(reponse)
infos_joueur_pickled = conn.recv(2048)
infos_joueur = pickle.loads(infos_joueur_pickled)
print(infos_joueur)
else:
print("No")
reponse = pickle.dumps("No")
conn.send(reponse)
conn.close()
except:
break
print("Connexion perdu")
# conn.close()
while True:
conn, addr = socket_de_connexion.accept()
print("Connecté à: ", addr)
start_new_thread(threaded_client, (conn,))
最佳答案
如果希望它是相同的套接字,则必须在窗口之间共享相同的套接字。
在我的解决方案中,我创建了一个处理套接字的类(在这种情况下,我使用QTcpSocket),如果您想处理其中存在信息交换的逻辑,则必须实现一个Command。
import pickle
import logging
from PyQt5 import QtCore, QtGui, QtWidgets, QtNetwork
logging.basicConfig(level=logging.DEBUG)
SERVER = "192.168.100.195"
PORT = 5555
class Command:
def process_message(self, msg):
pass
class Client(QtCore.QObject):
def __init__(self, parent=None):
super().__init__(parent)
self._socket = QtNetwork.QTcpSocket(self)
self.socket.connected.connect(self._handle_connected)
self.socket.readyRead.connect(self._handle_readyRead)
self.socket.stateChanged.connect(self._handle_state_changed)
self._command = None
@property
def command(self):
return self._command
@command.setter
def command(self, command):
self._command = command
def connectTo(self, host, port):
self.socket.connectToHost(host, port)
def disconnect(self):
self.socket.disconnectFromHost()
@property
def socket(self):
return self._socket
@QtCore.pyqtSlot()
def _handle_connected(self):
logging.debug("Connected")
@QtCore.pyqtSlot(QtNetwork.QAbstractSocket.SocketState)
def _handle_state_changed(self, state):
logging.debug("state: %s" % state)
@QtCore.pyqtSlot()
def _handle_readyRead(self):
msg = self.read_data()
logging.debug("receive message: %s" % msg)
if isinstance(self.command, Command):
answer = self.command.process_message(msg)
if isinstance(answer, str):
self.send_data(answer)
def encode_message(self, message):
return pickle.dumps(message)
def decode_message(self, message):
return pickle.loads(message)
def send_data(self, text):
logging.debug("send message: %s" % text)
data = self.encode_message(text)
self.socket.write(data)
def read_data(self):
data = self.socket.readAll()
msg = self.decode_message(data)
return msg
class CodeCommand(QtCore.QObject, Command):
received = QtCore.pyqtSignal(bool)
def __init__(self, code="", parent=None):
super().__init__(parent)
self._code = code
@property
def code(self):
return self._code
def process_message(self, msg):
if msg == "Connecté!":
return "join"
elif msg == "code?":
return self.code
self.send_data(self.code)
elif msg == "No":
self.received.emit(False)
elif msg == "Yes":
self.received.emit(True)
class VerificationDialog(QtWidgets.QDialog):
def __init__(self, client, parent=None):
super().__init__(parent)
self._client = client
self.code_le = QtWidgets.QLineEdit(placeholderText=self.tr("Code"))
code_validator = QtGui.QRegExpValidator(QtCore.QRegExp(r"^[0-9]{4}"))
self.code_le.setValidator(code_validator)
confirm_btn = QtWidgets.QPushButton(self.tr("Confirm"))
cancel_btn = QtWidgets.QPushButton(self.tr("Cancel"))
gridlayout = QtWidgets.QGridLayout(self)
gridlayout.addWidget(
QtWidgets.QLabel(self.tr("Invitation Code:")),
0,
0,
alignment=QtCore.Qt.AlignRight,
)
gridlayout.addWidget(self.code_le, 0, 1, alignment=QtCore.Qt.AlignLeft)
gridlayout.addWidget(confirm_btn, 1, 0, alignment=QtCore.Qt.AlignRight)
gridlayout.addWidget(cancel_btn, 1, 1, alignment=QtCore.Qt.AlignLeft)
gridlayout.setColumnStretch(0, 1)
gridlayout.setColumnStretch(1, 1)
self.code_le.setFixedSize(100, 25)
confirm_btn.setFixedSize(100, 40)
cancel_btn.setFixedSize(100, 40)
size = self.sizeHint()
self.setFixedSize(size)
confirm_btn.clicked.connect(self.confirm)
cancel_btn.clicked.connect(self.cancel)
@QtCore.pyqtSlot()
def confirm(self):
code = self.code_le.text()
command = CodeCommand(code)
command.received.connect(self.on_received)
self.client.command = command
self.client.connectTo(SERVER, PORT)
@QtCore.pyqtSlot()
def cancel(self):
self.client.disconnect()
self.reject()
@QtCore.pyqtSlot(bool)
def on_received(self, state):
if state:
self.accept()
else:
messagebox = QtWidgets.QMessageBox()
messagebox.setIcon(QtWidgets.QMessageBox.Critical)
messagebox.setText("Fault! The code is invalid!")
messagebox.setInformativeText(
"Please check the validity of the code. The program will now exit."
)
messagebox.setWindowTitle("Oops!")
messagebox.setStandardButtons(QtWidgets.QMessageBox.Ok)
messagebox.exec_()
QtCore.QCoreApplication.quit()
@property
def client(self):
return self._client
class TestDialog(QtWidgets.QDialog):
def __init__(self, client, parent=None):
super().__init__(parent)
self._client = client
self.username_le = QtWidgets.QLineEdit()
self.color_cmb = QtWidgets.QComboBox()
self.color_cmb.addItems(["Couleur 1", "Couleur 2", "Couleur 3"])
confirm_btn = QtWidgets.QPushButton(self.tr("Confirm"))
cancel_btn = QtWidgets.QPushButton(self.tr("Cancel"))
gridlayout = QtWidgets.QGridLayout(self)
gridlayout.addWidget(
QtWidgets.QLabel(self.tr("Username to display during the game:")), 0, 0
)
gridlayout.addWidget(self.username_le, 0, 1)
gridlayout.addWidget(QtWidgets.QLabel(self.tr("Please choose a color:")), 1, 0)
gridlayout.addWidget(self.color_cmb, 1, 1)
lay = QtWidgets.QHBoxLayout()
lay.addStretch()
lay.addWidget(confirm_btn)
lay.addWidget(cancel_btn)
gridlayout.addLayout(lay, 3, 0, 1, 2)
gridlayout.setRowStretch(2, 1)
self.resize(640, 325)
cancel_btn.clicked.connect(self.reject)
confirm_btn.clicked.connect(self.confirm)
@QtCore.pyqtSlot()
def confirm(self):
self.client.send_data("test")
self.accept()
@property
def client(self):
return self._client
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self._client = Client()
commands_menu = self.menuBar().addMenu("Commands")
verification_action = commands_menu.addAction("Verification")
test_action = commands_menu.addAction("Test")
verification_action.triggered.connect(self.verification)
test_action.triggered.connect(self.test)
@property
def client(self):
return self._client
@QtCore.pyqtSlot()
def verification(self):
d = VerificationDialog(self.client)
d.exec_()
@QtCore.pyqtSlot()
def test(self):
self.client.command = None
d = TestDialog(self.client)
d.exec_()
def main():
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
关于python-3.x - 在客户端应用程序上将一个套接字与多个窗口一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62332412/