Я пытаюсь создать приложение чата с графическим интерфейсом PyQt 4. Я решил "поместить" принимающую часть в другой поток, который начинается с приложения.
Проблема в том, что клиент не получает никакихданные с сервера.Я не знаю, что делать ... Это из-за нити?Прием находится в цикле while
, поэтому он получает данные "24/7". Кажется, он должен работать.Что я делаю не так?
Мой код выглядит так:
server.py
:
HEADER_LENGTH = 10
IP = "127.0.0.1"
PORT = 1234
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((IP, PORT))
server_socket.listen()
sockets_list = [server_socket]
clients = {}
def receive_message(client_socket):
try:
message_header = client_socket.recv(HEADER_LENGTH)
if not len(message_header):
return False
message_length = int(message_header.decode("utf-8"))
return {"header": message_header, "data": client_socket.recv(message_length)}
except:
return False
while True:
read_sockets, _, exception_sockets = select.select(sockets_list, [], sockets_list)
for notified_socket in read_sockets:
if notified_socket == server_socket:
client_socket, client_address = server_socket.accept()
user = receive_message(client_socket)
if user is False:
continue
sockets_list.append(client_socket)
clients[client_socket] = user
print(f"Accepted new connection from {client_address[0]}:{client_address[1]} username: {user['data'].decode('utf-8')}")
else:
message = receive_message(notified_socket)
if message is False:
print(f"Closed connection from {clients[notified_socket]['data'].decode('utf-8')}")
sockets_list.remove(notified_socket)
del clients[notified_socket]
continue
user = clients[notified_socket]
print(f"Received message from {user['data'].decode('utf-8')}: {message['data'].decode('utf-8')}")
for client_socket in clients:
if client_socket != notified_socket:
client_socket.send(user['header'] + user['data'] + message['header'] + message['data'])
for notified_socket in exception_sockets:
sockets_list.remove(notified_socket)
del clients[notified_socket]
client.py
:
# -*- coding: utf-8 -*-
from PyQt4 import QtCore, QtGui
import socket
import select
import errno
import sys
HEADER_LENGTH = 10
IP = "127.0.0.1"
PORT = 1234
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((IP, PORT))
client_socket.setblocking(False)
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(800, 600)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth())
MainWindow.setSizePolicy(sizePolicy)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(_fromUtf8("logo.ico")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
MainWindow.setWindowIcon(icon)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.chatWindow = QtGui.QTextBrowser(self.centralwidget)
self.chatWindow.setGeometry(QtCore.QRect(10, 10, 451, 501))
self.chatWindow.setObjectName(_fromUtf8("chatWindow"))
self.chatInput = QtGui.QTextEdit(self.centralwidget)
self.chatInput.setGeometry(QtCore.QRect(10, 520, 351, 31))
self.chatInput.setObjectName(_fromUtf8("chatInput"))
self.sendButton = QtGui.QPushButton(self.centralwidget)
self.sendButton.setGeometry(QtCore.QRect(370, 520, 91, 31))
self.sendButton.setObjectName(_fromUtf8("sendButton"))
self.usersWindow = QtGui.QTextBrowser(self.centralwidget)
self.usersWindow.setGeometry(QtCore.QRect(470, 50, 321, 201))
self.usersWindow.setObjectName(_fromUtf8("usersWindow"))
self.usersLabel = QtGui.QLabel(self.centralwidget)
self.usersLabel.setGeometry(QtCore.QRect(560, 10, 171, 31))
self.usersLabel.setStyleSheet(_fromUtf8("font: 20pt \"MS Shell Dlg 2\";"))
self.usersLabel.setObjectName(_fromUtf8("usersLabel"))
MainWindow.setCentralWidget(self.centralwidget)
self.usernameSelect = QtGui.QTextEdit(self.centralwidget)
self.usernameSelect.setGeometry(QtCore.QRect(470, 270, 321, 31))
self.usernameSelect.setStyleSheet(_fromUtf8("font: 12pt \"MS Shell Dlg 2\";"))
self.usernameSelect.setObjectName(_fromUtf8("textEdit"))
self.usernameSetButton = QtGui.QPushButton(self.centralwidget)
self.usernameSetButton.setGeometry(QtCore.QRect(580, 310, 111, 41))
self.usernameSetButton.setStyleSheet(_fromUtf8("font: 12pt \"MS Shell Dlg 2\";"))
self.usernameSetButton.setObjectName(_fromUtf8("pushButton"))
self.menubar = QtGui.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
self.menubar.setObjectName(_fromUtf8("menubar"))
self.menuFile = QtGui.QMenu(self.menubar)
self.menuFile.setObjectName(_fromUtf8("menuFile"))
self.menuEdit = QtGui.QMenu(self.menubar)
self.menuEdit.setObjectName(_fromUtf8("menuEdit"))
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtGui.QStatusBar(MainWindow)
self.statusbar.setObjectName(_fromUtf8("statusbar"))
MainWindow.setStatusBar(self.statusbar)
self.actionClose = QtGui.QAction(MainWindow)
self.actionClose.setObjectName(_fromUtf8("actionClose"))
# self.actionChangeUsername = QtGui.QAction(MainWindow)
# self.actionChangeUsername.setObjectName(_fromUtf8("actionChangeUsername"))
self.menuFile.addAction(self.actionClose)
# self.menuEdit.addAction(self.actionChangeUsername)
self.menubar.addAction(self.menuFile.menuAction())
self.menubar.addAction(self.menuEdit.menuAction())
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
self.sendButton.clicked.connect(self.send_message)
self.actionClose.triggered.connect(self.close_application)
self.usernameSetButton.clicked.connect(self.set_username)
self.start_thread()
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(_translate("MainWindow", "Pocket Chat", None))
self.sendButton.setText(_translate("MainWindow", "Send", None))
self.usersLabel.setText(_translate("MainWindow", "Active users", None))
self.usernameSelect.setHtml(_translate("MainWindow",
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'MS Shell Dlg 2\'; font-size:12pt; font-weight:400; font-style:normal;\">\n"
"<p align=\"center\" style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><br /></p></body></html>",
None))
self.usernameSetButton.setText(_translate("MainWindow", "Set username", None))
self.menuFile.setTitle(_translate("MainWindow", "File", None))
self.menuEdit.setTitle(_translate("MainWindow", "Edit", None))
self.actionClose.setText(_translate("MainWindow", "Close", None))
def send_message(self):
message = self.chatInput.toPlainText()
# print(message)
if message:
message = message.encode('utf-8')
message_header = f"{len(message):<{HEADER_LENGTH}}".encode('utf-8')
client_socket.send(message_header + message)
def set_username(self):
my_username = self.usernameSelect.toPlainText()
username = my_username.encode('utf-8')
username_header = f"{len(username):<{HEADER_LENGTH}}".encode('utf-8')
client_socket.send(username_header + username)
self.usernameSelect.deleteLater()
self.usernameSetButton.deleteLater()
def close_application(self):
sys.exit(0)
def start_thread(self):
self.thread = ReceiveThread()
self.thread.data_received.connect(self.on_receive_data)
self.thread.start()
def on_receive_data(self, username, message):
if self.chatWindow.toPlainText() != "":
current_chat = self.chatWindow.toPlainText()
print('heloo')
self.chatWindow.setText((current_chat + "\n" + f"{username}: {message}"))
else:
self.chatWindow.setText(f"{username}: {message}")
class ReceiveThread(QtCore.QThread):
data_received = QtCore.pyqtSignal(object)
def run(self):
while True:
try:
while True:
# receive things
username_header = client_socket.recv(HEADER_LENGTH)
if not len(username_header):
print("Connection closed by the server.")
sys.exit()
username_length = int(username_header.decode('utf-8'))
username = client_socket.recv(username_length).decode('utf-8')
message_header = client_socket.recv(HEADER_LENGTH)
message_length = int(message_header.decode('utf-8'))
message = client_socket.recv(message_length).decode('utf-8')
print(f"{username}: {message}") # Not working because It's not receiving data
# self.data_received.emit(str(username), str(message)) # Same here not working
except IOError as e:
if e.errno != errno.EAGAIN and e.errno != errno.EWOULDBLOCK:
print("Reading error", str(e))
sys.exit()
continue
except Exception as e:
print("General error", str(e))
sys.exit()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
MainWindow = QtGui.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
Я также должен сказать, что он основан на руководствах Sentdex на YouTube и, ну, он работает, но без графического интерфейса - на основе консоли.Я действительно понятия не имею, что происходит.Я отладил его, и он даже не достигает части username_header = client_socket.recv(HEADER_LENGTH)
в классе ReceiveThread(QtCore.QThread)
... Цикл работает, но ничего в цикле не происходит.