En lisant ta question je te soupçonne d'essayer de lire le header à chaque trame TCP. En reprenant mon example si dessus, tu dois essayer de lire le header pour la première trame TCP que tu reçois, ce header sera celui du message A.
Par contre si tu essaye de lire un header en utilisant le début de la deuxième trame TCP (càd la fin du message A + le message B) tu va te retrouver avec des infos qui n'ont ni queue ni tête (= des IDs incorrects/inexistants).
Ce qu'il faut faire pour bien gérer tout ça c'est avoir un Buffer dans lequel tu push tes trames TCP.
Voila ce que moi j'utilise dans mon propre bot MITM (nodejs). Il faudra surement l'adapter à votre langage/architecture :
GameSocket.js
while ((chunk = this._rawSocket.read()) !== null) {
this._logger.debug('Incoming data', { length: chunk.length })
this._logger.info({ raw: true, dir: 'in', data: chunk, origin: this.origin})
this._packetBuffer.fill(chunk)
}
const messages = this._packetBuffer.checkForCompleteMessage()
GameSocket c'est une classe qui wrappe la socket nodejs. Là dedans j'ai un
_packetBuffer
dans lequel je push tous mes chunks (= trame TCP) avec la méthode
fill
.
Tant que j'ai des infos à lire sur la socket je push. Quand j'ai plus rien à lire je regarde si je peux extraire des messages avec la méthode
checkForCompleteMessage
PacketBuffer
constructor() {
this._buffer = new ByteArray() // Buffer Big endian
}
fill(data) {
this._buffer.writeBytes(data)
}
checkForCompleteMessage() {
const messages = []
this._logger.debug('Checking for complete messages')
// eslint-disable-next-line no-constant-condition
while (true) {
const message = this._check()
if (!message) {
break
}
messages.push(message)
}
this._buffer.position = this._buffer.length
return messages
}
_check() {
this._buffer.position = 0
if (this._buffer.bytesAvailable < 2) {
this._logger.debug('Not enougth bytes to read a header')
return null
}
const { messageId, length } = MessageForge.readHeader(
this._buffer,
this.origin,
)
if (this._buffer.bytesAvailable < length) {
this._logger.debug('Message is incomplete', {
messageId,
messageLength: length,
bytesAvailable: this._buffer.bytesAvailable,
})
return null
}
const messageData = new ByteArray()
const MessageConstructor = Messages.getById(messageId)
if (length > 0) {
this._buffer.readBytes(messageData, 0, length)
}
const newBuffer = new ByteArray()
this._buffer.readBytes(newBuffer)
this._buffer = newBuffer
this._logger.debug('Message complete', {
messageId,
messageLength: length,
messageDataLength: messageData.length,
newBufferLength: this._buffer.length,
newBufferBytesAvailable: this._buffer.bytesAvailable,
newBufferPosition: this._buffer.position,
})
return new MessageConstructor({ data: messageData })
}
En gros quand j'ai plus rien à lire je regarde ce que j'ai dans mon buffer. Je commence par lire les 2premiers octets pour lire un header. Avec la length décrite dans le header je regarde si j'ai encore assez de données dans mon buffer pour avoir un message entier. Si oui, parfait je l'extrait et slice mon buffer. Sinon bien, rien de plus, le serveur doit m'envoyer encore des infos !
Avec tout ça normalement vous devriez arriver à qqch de pas mal !