小编典典

当帧数和每帧长度不固定时,如何在套接字编程中从服务器获取所有电报?

java

这是我的第一个问题,英语不是我的母语。如果我没有清楚说明,请告诉我。

背景:在IEC104电气通信协议中,当客户端请求一次时,服务器可能会在一个tcp套接字包中以多于一帧的电报响应。所有帧均以“
68”开头,然后是电报的长度。例如:client:68 14 00 00 00 00 67 01 06 00 01 00 00 00 00 1C
79 BA 0B AE 04 11 //时间同步激活。服务器:68 14 00 00 00 00 67 01 07 00 01 00 00 00
00 1C 79 BA 0B AE 04 11
//时间同步确认,这是预期的响应。但是有时服务器会在时间同步确认之前回复其他电报。例如,下面是来自服务器的群发电报:
680E00000000460104000100000000806820020000001E02030001004A040001E50B810001010045040001060F81000101006828040000002402030001001100000000000000FE9A80000101001300000100DE4100FE9A800001010068BE06000000250C03000100C80000000000008050008100010100C90000000000008050008100010100CA0000000000008050008100010100CB0000000000008050008100010100CC0000000000008050008100010100CD0000000000008050008100010100C8000000000000814E008200010100C9000000000000814E008200010100CA000000000000814E008200010100CB000000000000814E008200010100CC000000000000814E008200010100CD00000000000081500082000101006814080000006701400001000000008E869217BF0C6368FA0A000000251003000100CA0000000000001950009A00010100CB0000000000001950009A00010100CC0000000000001950009A00010100CD0000000000001950009A00010100C80000000000001A4E009B00010100C90000000000001A4E009B00010100CA0000000000001A4E009B00010100CB0000000000001A4E009B00010100CC0000000000001A4E009B00010100CD0000000000001A51009B00010100C80000000000001B4E009C00010100C90000000000001B4E009C00010100CA0000000000001B4E009C00010100CB0000000000001B4E009C00010100CC0000000000001B4E009C00010100CD0000000000001B4E009C0001010068FA0C000000251003000100C80000000000001C4E009D00010100C90000000000001C4E009D00010100CA0000000000001C4E009D00010100CB0000000000001C4F009D00010100CC0000000000001C4F009D00010100CD0000000000001C4F009D00010100C80000000000001D4E009E00010100C90000000000001D4F009E00010100CA0000000000001D4F009E00010100CB0000000000001D4F009E00010100CC0000000000001D4F009E00010100CD0000000000001D4F009E00010100C80000000000001E4E009F00010100C90000000000001E4E009F00010100CA0000000000001E4E009F00010100CB0000000000001E4F009F0001010068FA0E000000251003000100CC0000000000001E4F009F00010100CD0000000000001E4F009F00010100C80000000000001F4E00A000010100C90000000000001F4E00A000010100CA0000000000001F4E00A000010100CB0000000000001F4E00A000010100CC0000000000001F4E00A000010100CD0000000000001F4E00A000010100C8000000000000004E00A100010100C9000000000000004E00A100010100CA000000000000004F00A100010100CB000000000000004F00A100010100CC000000000000004F00A100010100CD000000000000004F00A100010100C8000000000000015000A200010100C9000000000000015000A2000101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000啊〜抱歉,这么长时间……。

有八个“ 68”,即包括8帧电报。在这种情况下,我有一个问题要从服务器收集电报。如上所述,我不知道电报的帧数和每帧的长度,因此我定义了大数组byte
[2048]来包含所有电报,然后将其拆分为11个字符串(新String [11])。这在大多数情况下都有效,但显然设计不好。

 byte[] boTimeSync = HexStrToByte.hexStringToBytes(Setting.TIMESYNC);
            out.write(boTimeSync);
            out.flush(); 
            VisibleFrame.updateTextArea(Setting.TIMESYNC.toUpperCase()+"\n");
            VisibleFrame.updateTextArea(TimeParsing.parsing(Setting.TIMESYNC.toUpperCase())+"\n");
            byte[] biTimeSync = new byte[2048];         
            bin.read(biTimeSync);
            str = t104.ByteToStr.byteToStr(biTimeSync);
            String[] bi = new String[11]; 
            bi = SplitTele.splitTele(str);

那么,由于InputStream.available()不适合网络编程,如何获取所有帧?


阅读 247

收藏
2020-11-30

共1个答案

小编典典

您需要使用DataInputStream

int start;
do
{
    start = din.read();
} while (start != -1 && start != 0x68);
if (start == -1)
    throw new EOFException();
int length = din.readUnsignedByte();
byte[] message = new byte[length];
din.readFully(message);
return message;

除非响应包含某种类型的请求ID,否则无法“响应特定请求查找最后一帧”的解决方案。

2020-11-30