One big problem I see is this:
Qt Code:
self.connect(thread, SIGNAL("finished()"), thread, SLOT("deleteLater()"))To copy to clipboard, switch view to plain text mode
What happens if you delete or comment that line?
One big problem I see is this:
Qt Code:
self.connect(thread, SIGNAL("finished()"), thread, SLOT("deleteLater()"))To copy to clipboard, switch view to plain text mode
What happens if you delete or comment that line?
By commenting this line it seems that my application does not crash easilygood catch! (I will like to have more explanations)
But the out of sync / corruption problem is not resolved (I also join another code extract below the logs) :
Note: red color is used to distinguish what the client prints
...
b'\x00\x14\x00\x00\x00@\x00\x00\xcf\x97\x04.\xb2\x d0\x00\x00\x05\xfa\x00\x00\x00\x00'
Bytes available: 22
BlockSize: 20
SIZE: 22
b'\x00\x14\x00\x00\x00@\x00\x00\xcf\x97\x04.\xb2\x d0\x00\x00\x06E\x00\x00\x00\x00'
Bytes available: 22
BlockSize: 20
SIZE: 22
b'\x00\x14\x00\x00\x00@\x00\x00\xcf\x97\x04.\xb2\x d0\x00\x00\x06q\x00\x00\x00F'
Bytes available: 22
GameServer: Bug of QTcpSocket?!
QDataStream status(): 1
...
--> the status seems to say that there has been a reading that has begun too soon :/
And another log that show a corruption case:
Notes:
- at some point, I have moved a QGraphicsItem very quickly in order to generate a lot of network packets
- the actions 2827 or 2828 are not valid numbers (valid ones are 0 and 1)
- the repetition of 2827 and 2828 seems strange...
...
b'\x00\x14\x00\x00\x00@\x00\x02f \x047:\xd0\x00\x00\x03\xa4\x00\x00\x02K'
Bytes available: 22
BlockSize: 20
SIZE: 22
b'\x00\x14\x00\x00\x00@\x00\x02f \x047:\xd0\x00\x00\x03?\x00\x00\x02D'
Bytes available: 22
BlockSize: 20
SIZE: 22
b'\x00\x14\x00\x00\x00@\x00\x02f \x047:\xd0\x00\x00\x03\x11\x00\x00\x02\x03'
Bytes available: 22
BlockSize: 20
SIZE: 22
b'\x00\x14\x00\x00\x00@\x00\x02f \x047:\xd0\x00\x00\x03!\x00\x00\x01\xa8'
Bytes available: 22
BlockSize: 20
SIZE: 22
SIZE: 22
b'\x00\x14\x00\x00\x00@\x00\x02f \x047:\xd0\x00\x00\x03c\x00\x00\x01P'
b'\x00\x14\x00\x00\x00@\x00\x02f \x047:\xd0\x00\x00\x03\xb5\x00\x00\x00\xfc'
Bytes available: 22
BlockSize: 20
Bytes available: 4118
BlockSize: 20
Bytes available: 4096
BlockSize: 20
Bytes available: 4074
BlockSize: 20
Bytes available: 4052
BlockSize: 20
Bytes available: 4030
BlockSize: 2828
GameSeverThread: action [2827] unhandled!
Bytes available: 4020
BlockSize: 2827
GameSeverThread: action [2828] unhandled!
Bytes available: 4010
BlockSize: 2828
GameSeverThread: action [2827] unhandled!
Bytes available: 4000
BlockSize: 2827
GameSeverThread: action [2828] unhandled!
Bytes available: 3990
BlockSize: 2828
GameSeverThread: action [2827] unhandled!
Bytes available: 3980
BlockSize: 2827
...
Here are the code of the client thread that sends the byte arrays:
Qt Code:
def __init__(self, socket, request, rqLock, parent): super(HandleClientRequestThread, self).__init__(parent) self.socket = socket self.rqLock = rqLock self.request = request self.__toSend = [] def run(self): while True: self.rqLock.lock() length = len(self.request) while length > 0: r = self.request.pop(0) print(r) self.socket.write(r) else: print("socket is not connected") length = len(self.request) self.rqLock.unlock() self.msleep(10)To copy to clipboard, switch view to plain text mode
The client thread read the list "request" where packets are stored into by the method issueRequest() below. This later method is called
through a slot that is connected to a signal sent by a QGraphicsItem when this one has moved.
Qt Code:
def __init__(self, gameWindow): super(GameClient, self).__init__(None) self.myPlayerId = 0 self.resetWork() self.connect(self.socket, SIGNAL("connected()"), self.startNetworkThread) self.connect(self.socket, SIGNAL("readyRead()"), self.readFirstResponse) self.connect(self.socket, SIGNAL("disconnected()"), self.serverHasStopped) self.connect(self.socket, SIGNAL("error(QAbstractSocket::SocketError)"), self.serverHasError) def startNetworkThread(self): self.thread = HandleClientRequestThread(self.socket, self.request, self.rqLock, self) self.connect(self.thread, SIGNAL("finished()"), self.thread, SLOT("deleteLater()")) self.thread.start() def issueRequest(self, action, params): stream.writeUInt16(0) stream.writeUInt16(action) stream.writeUInt16(self.gameId) stream.writeUInt32(self.myPlayerId) for arg in params: arg.writeOnStream(stream) stream.device().seek(0) print("SIZE: %d" % req.size()) stream.writeUInt16(req.size() - SIZEOF_UINT16) self.rqLock.lock() self.request.append(req) self.rqLock.unlock()To copy to clipboard, switch view to plain text mode
I hope you will have some new hints to resolve my problem.
Best regards.
In general something causes your socket to go out of "connected" state which causes your thread to exit which causes it to be deleted (as tbscope noticed) which causes you to access a stale object upon receiving data from the socket. First thing you should do is to get rid of the state check. It'd be best if you turned your synchronous approach into asynchronous that uses signals and slots so that you can get rid of the thread and possibly solve all your problems in one go.
I've already modify the client to send packets without the intermediary thread, and it does not resolve the problem :/ (Moreover if my client is disconnected it will print this fact).
So there was just threads at the server side, and checking the state here is precisely good in order to avoid accessing the socket if it is disconnected.
(BTW, my client is more asynchronous with a threading approach than without one)
I don't think modifying the client will solve the server's problems...
I suppose that it is a problem at the server side, but maybe packets are "incorrectly" sent at the client side.
I will code the server in a mono-threaded approach to see if it resolves problems, but I will like to know what is wrong with my current code.
Thanks for your help.
In short you are probably assuming too many things. Client and server are autonomous systems and they have to be treated like that.
Bookmarks