2 개 이상의 클라이언트에 동시에 데이터를 반환 할 수있는 PyQt를 사용하여 QTcpServer를 만들려고합니다. 나는 이것이 스레딩을 필요로한다고 가정한다.PyQt QTcpServer : 데이터를 여러 클라이언트에 반환하는 방법은 무엇입니까?
내 시스템의 PyQt4에 포함 된 threadedfortuneserver.py 예제를 테스트 케이스로 사용하여/usr/share/doc/python-qt4-doc/examples/network에 있습니다. 여러 클라이언트를 연결하려고합니다. 클라이언트 중 한 명이 재산을 요구할 때마다 다른 클라이언트는 "클라이언트 X가 방금받은 돈을 'ㅋㅋㅋ'와 같은 메시지로 업데이트합니다.
나는 fortuneserver/client 프로그램의 작동 방식을 이해하고 있지만, 운세가 클라이언트에 다시 전송 된 후 클라이언트 연결이 즉시 종료 된 것처럼 보입니다. 내 구체적인 질문은 다음과 같습니다
는 클라이언트 중 하나는 재산을 요청하는 모든 시간이, 다른 클라이언트가 업데이트 할 수 있도록 모든 연결이 열려 유지할 수 있습니까?
그렇다면 연결된 클라이언트를 추적하고 루프하는 가장 좋은 방법은 무엇입니까? 내가 여러 클라이언트가 상호 작용할 수있는 응용 프로그램을 개발하기를 원하기 때문에
이 나를 위해 심각한 걸림돌이며, 각 클라이언트는 다른 클라이언트의 행동에 대해 업데이트 할 수 있습니다.
미리 도움을 주셔서 감사합니다. 제공 할 수있는 다른 정보가 있으면 알려주십시오.
나는 this thread을 찾았지만 사용할 구체적인 정보가 충분하지 않았습니다. Python 소켓 패키지에 대한 다른 논의가 있었지만, PyQt를 사용할 때 서버가 QTcpServer 여야하므로 모든 것이 훌륭하게 작동한다는 것을 이해합니다.
*** 편집 ***
여기 내 해결책의 시작 단계입니다. 기본 서버와 클라이언트를 만들었습니다. 서버는 클라이언트가 라인 편집 상자에 입력 한 것을 다시 전송합니다.
저는 이것을 Rapid GUI Programming with Python and Qt의 18 장에있는 "buildingservices"예제를 기반으로합니다.
내가 한 주요 변경 사항은 이제 스레드가 계속 무기한 실행되고 소켓이 열려있어 클라이언트가 보내는 데이터를 수신한다는 것입니다.
여러 클라이언트를 잘 처리합니다. 그것은 확실히 못생긴 것이지만 좋은 출발점이라고 생각합니다.
한 클라이언트가 텍스트를 입력 할 때마다 (예 : 일반적인 채팅 프로그램처럼) 각 클라이언트에 알릴 수 있어야합니다.
또한 내가 다루는 사람에 대한 아이디어를 제공하기 위해 나는 전문 프로그래머가 아닙니다. 저는 수년간 훈련되지 않은 스크립팅을해온 물리학 자요. 하지만 데이터를 전달할 수있는 기본적인 서버/클라이언트 프로그램을 개발하려고합니다.
도움이나 제안을 보내 주셔서 감사합니다.
SERVER :
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtNetwork import *
PORT = 9999
SIZEOF_UINT16 = 2
class Thread(QThread):
#lock = QReadWriteLock()
def __init__(self, socketId, parent):
super(Thread, self).__init__(parent)
self.socketId = socketId
def run(self):
self.socket = QTcpSocket()
if not self.socket.setSocketDescriptor(self.socketId):
self.emit(SIGNAL("error(int)"), socket.error())
return
while self.socket.state() == QAbstractSocket.ConnectedState:
nextBlockSize = 0
stream = QDataStream(self.socket)
stream.setVersion(QDataStream.Qt_4_2)
if (self.socket.waitForReadyRead(-1) and
self.socket.bytesAvailable() >= SIZEOF_UINT16):
nextBlockSize = stream.readUInt16()
else:
self.sendError("Cannot read client request")
return
if self.socket.bytesAvailable() < nextBlockSize:
if (not self.socket.waitForReadyRead(-1) or
self.socket.bytesAvailable() < nextBlockSize):
self.sendError("Cannot read client data")
return
textFromClient = stream.readQString()
textToClient = "You wrote: \"{}\"".format(textFromClient)
self.sendReply(textToClient)
def sendError(self, msg):
reply = QByteArray()
stream = QDataStream(reply, QIODevice.WriteOnly)
stream.setVersion(QDataStream.Qt_4_2)
stream.writeUInt16(0)
stream.writeQString("ERROR")
stream.writeQString(msg)
stream.device().seek(0)
stream.writeUInt16(reply.size() - SIZEOF_UINT16)
self.socket.write(reply)
def sendReply(self, text):
reply = QByteArray()
stream = QDataStream(reply, QIODevice.WriteOnly)
stream.setVersion(QDataStream.Qt_4_2)
stream.writeUInt16(0)
stream.writeQString(text)
stream.device().seek(0)
stream.writeUInt16(reply.size() - SIZEOF_UINT16)
self.socket.write(reply)
class TcpServer(QTcpServer):
def __init__(self, parent=None):
super(TcpServer, self).__init__(parent)
def incomingConnection(self, socketId):
self.thread = Thread(socketId, self)
self.thread.start()
class ServerDlg(QPushButton):
def __init__(self, parent=None):
super(ServerDlg, self).__init__(
"&Close Server", parent)
self.setWindowFlags(Qt.WindowStaysOnTopHint)
self.tcpServer = TcpServer(self)
if not self.tcpServer.listen(QHostAddress("0.0.0.0"), PORT):
QMessageBox.critical(self, "Threaded Server",
"Failed to start server: {}".format(
self.tcpServer.errorString()))
self.close()
return
self.connect(self, SIGNAL("clicked()"), self.close)
font = self.font()
font.setPointSize(24)
self.setFont(font)
self.setWindowTitle("Threaded Server")
app = QApplication(sys.argv)
form = ServerDlg()
form.show()
form.move(0, 0)
app.exec_()
CLIENT :로는 아마 당신의 대부분을 exasperatingly 분명했다
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtNetwork import *
PORT = 9999
SIZEOF_UINT16 = 2
class Form(QDialog):
def __init__(self, parent=None):
super(Form, self).__init__(parent)
# Ititialize socket
self.socket = QTcpSocket()
# Initialize data IO variables
self.nextBlockSize = 0
self.request = None
# Create widgets/layout
self.browser = QTextBrowser()
self.lineedit = QLineEdit("Texty bits")
self.lineedit.selectAll()
self.connectButton = QPushButton("Connect")
self.connectButton.setDefault(False)
self.connectButton.setEnabled(True)
layout = QVBoxLayout()
layout.addWidget(self.browser)
layout.addWidget(self.lineedit)
layout.addWidget(self.connectButton)
self.setLayout(layout)
self.lineedit.setFocus()
# Signals and slots for line edit and connect button
self.lineedit.returnPressed.connect(self.sendToServer)
self.connectButton.released.connect(self.connectToServer)
self.setWindowTitle("Client")
# Signals and slots for networking
self.socket.readyRead.connect(self.readFromServer)
self.socket.disconnected.connect(self.serverHasStopped)
self.connect(self.socket,
SIGNAL("error(QAbstractSocket::SocketError)"),
self.serverHasError)
# Update GUI
def updateUi(self, text):
self.browser.append(text)
# Create connection to server
def connectToServer(self):
self.connectButton.setEnabled(False)
print("Connecting to server")
self.socket.connectToHost("localhost", PORT)
# Send data to server
def sendToServer(self):
self.request = QByteArray()
stream = QDataStream(self.request, QIODevice.WriteOnly)
stream.setVersion(QDataStream.Qt_4_2)
stream.writeUInt16(0)
stream.writeQString(self.lineedit.text())
stream.device().seek(0)
stream.writeUInt16(self.request.size() - SIZEOF_UINT16)
self.socket.write(self.request)
self.nextBlockSize = 0
self.request = None
self.lineedit.setText("")
# Read data from server and update Text Browser
def readFromServer(self):
stream = QDataStream(self.socket)
stream.setVersion(QDataStream.Qt_4_2)
while True:
if self.nextBlockSize == 0:
if self.socket.bytesAvailable() < SIZEOF_UINT16:
break
self.nextBlockSize = stream.readUInt16()
if self.socket.bytesAvailable() < self.nextBlockSize:
break
textFromServer = stream.readQString()
self.updateUi(textFromServer)
self.nextBlockSize = 0
def serverHasStopped(self):
self.socket.close()
def serverHasError(self):
self.updateUi("Error: {}".format(
self.socket.errorString()))
self.socket.close()
app = QApplication(sys.argv)
form = Form()
form.show()
app.exec_()