[英]Using a socket for a custom protocol over tcp
我的協議如下所示:
[size: UInt16][Channel: Uint16][Protobuff packet]
問題是,據我了解,tcp不能保證用戶發送的整個數據包將一並到達。 因此,從技術上講,可能會出現這樣的情況,即我無法一次獲得全部消息,甚至無法與該消息一起發送另一條消息的一部分。
這很簡單,當我只是假設我將立即獲取整個消息時,因為我只是從流中讀取前2個字節,制作了一個具有適當大小的read(buffer)
但是如果我開始,則稱為read(buffer)
考慮到停產的可能性,我不確定如何處理。 我嘗試了以下方法:
val input = clientSocket.getInputStream()
while (!isStopped) {
val bufferedInputStream: BufferedInputStream = BufferedInputStream(input)
val dataInputStream: DataInputStream = DataInputStream(bufferedInputStream)
var messageSize: Int? = null
var channel: Int? = null
while (true) {
if (messageSize == null) {
messageSize = dataInputStream.readUnsignedShort()
}
if (channel == null) {
channel = dataInputStream.readUnsignedShort()
}
var bytesRead = 0
var didReachEnd = false
val buffer = ByteArray(messageSize - 4)
while (bytesRead != -1 && bytesRead != messageSize) {
val temp = dataInputStream.read(buffer)
if (temp == -1) {
didReachEnd = true
} else {
bytesRead += temp
}
Logger.debug(this::class.java, "bytes read: $bytesRead out of $messageSize")
}
val packet = ChatChannel.Packet.parseFrom(buffer)
print(packet.chatMessage.messageText)
}
}
我嘗試通過從客戶端套接字執行以下操作來模仿消息拆分:
val chatPacket = ChatChannel.Packet.newBuilder().setChatMessage(chatChannel).build()
val sendPacket = Packet(0,chatPacket.toByteArray())
val sendPacketByteArray = sendPacket.toByteArray()
val halfPoint = sendPacketByteArray.size/2
val firstSlice = sendPacketByteArray.sliceArray(IntRange(0,halfPoint))
val secondSlice = sendPacketByteArray.sliceArray(IntRange(halfPoint,halfPoint+(halfPoint%2)))
s.getOutputStream().write(firstSlice)
sleep(200)
s.getOutputStream().write(secondSlice)
但是我的實現在第二次運行時就掛在了下面的行中:
bytesRead = dataInputStream.read(buffer,0,buffer.size)
我有一種關於套接字如何工作的想法,但是我看到的每個實現都假定當用戶發送完消息后,他將關閉連接,但在我的情況下,它是一個聊天程序,因此用戶只會關閉完成聊天時的連接。
我想實現的目標:
size
已滿 編輯:經過進一步研究,我發現可以在Java中與protobuf一起使用的MessageLite庫似乎具有稱為writeDelimitedTo(outputStream)和parseDelimitedFrom(inputStream)的方法,因此似乎大部分工作已為我完成。
兩件事情:
while (bytesRead != -1 && bytesRead != messageSize) {
bytesRead = dataInputStream.read(buffer,0,buffer.size)
對我來說似乎很奇怪。 您不增加bytesRead。 也就是說,如果messageSize為100,並且在第一次讀取中讀取了90個字節,則在第二次讀取中將讀取10個字節。 您不能簡單地說“ bytesRead + = ...”,因為它可能返回-1。 因此,您需要另一個變量。 檢查返回值是否為非負數,然后對byteCounter進行遞增。 該byteCounter需要與messageSize比較。
另外:如果您要做的只是為Google protobuf消息提供多個渠道,請不要這樣做! 創建包含protobuf消息和通道變量的protobuf消息。 那應該使生活更加輕松。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.