简体   繁体   English

Java SocketChannel读取整个字符串

[英]Java SocketChannel Read Entire String

In my current project, I am trying to transmit a string from one computer to another, and after finding and learning from numerous examples I have managed to get a basic form of communication working. 在我当前的项目中,我试图将字符串从一台计算机传输到另一台计算机,并且在从大量示例中找到并学习之后,我设法获得了一种基本的通信形式。

The issue I am having is if one computer tries sending a message that is too long, it seems to get broken up into multiple parts (roughly 3700 characters), and my parsing method fails. 我遇到的问题是,如果一台计算机尝试发送太长的消息,它似乎被分解成多个部分(大约3700个字符),并且我的解析方法失败。

I am using a Selector to iterate through all of the channels. 我正在使用选择器来遍历所有通道。 Here is the relevant code: 以下是相关代码:

if(key.isReadable()) {
    // Get the channel and read in the data
    SocketChannel keyChannel = (SocketChannel)key.channel();
    ByteBuffer buffer = buffers.get(keyChannel);
    int length  = 0;
    try {
        length = keyChannel.read(buffer);
    } catch ( IOException ioe) {
        closeChannel(keyChannel);
    }
    if(length > 0) {
        buffer.flip();
        // Gather the entire message before processing
        while( buffer.remaining() > 0) {
            byte[] data = new byte[buffer.remaining()];
            buffer.get(data);
            fireReceiveEvent(keyChannel, data);//Send the data for processing
        }
        buffer.compact();
    } else if (length < 0) {
        closeChannel(keyChannel);
    }
}

How can I guarantee that the entire message (regardless of length) is read at once before passing it along? 如何保证在传递消息之前立即读取整个消息(无论长度如何)?

After talking to numerous people that know more about this than I do. 与许多比我了解更多的人交谈之后。 The issue turns out to be that with TCP it is impossible to know when an entire "message" has arrived because there is no such thing as a message since TCP works on a two-way byte stream. 问题的根源在于,使用TCP不可能知道整个“消息”何时到达,因为没有消息之类的消息,因为TCP在双向字节流上工作。 The solution is to create your own protocol and implements your own definition of "message". 解决方案是创建您自己的协议并实现您自己的“消息”定义。

For my project, every message either starts with a [ or { and ends with a ] or } depending on the starting character. 对于我的项目,每条消息都以[{开头,并以]}结尾,具体取决于起始字符。 I search through the received data, and if there is a complete message, I grab it and pass it along to the handler. 我搜索接收到的数据,如果有完整的消息,则抓取并将其传递给处理程序。 Otherwise skip the channel, and wait for more to arrive. 否则,请跳过频道,然后等待更多内容到达。

Here is the final version of my code that handles the message receiving. 这是处理消息接收的代码的最终版本。

if(key.isReadable()) {
    // Get the channel and read in the data
    SocketChannel keyChannel = (SocketChannel)key.channel();
    ByteBuffer buffer = buffers.get(keyChannel);
    int length = 0;
    try {
        length = keyChannel.read(buffer);
    } catch ( IOException ioe) {
        key.cancel();
        closeChannel(keyChannel);
    }
    if (length > 0) {
        buffer.flip();
        // Gather the entire message before processing
        if (buffer.remaining() > 0) {
            byte[] data = new byte[buffer.remaining()];
            buffer.get(data);
            buffer.rewind();
            int index = 0;
            int i = 0;
            // Check for the beginning of a packet
            //[ = 91
            //] = 93
            //{ = 123
            //} = 125
            if (data[0] == 91 || data[0] == 123) {
                // The string we are looking for
                byte targetByte = (byte) (data[0] + 2);
                for (byte b : data) {
                    i += 1;
                    if (b == targetByte) {
                        index = i;
                        break;
                    }
                }
                if (index > 0) {
                    data = new byte[index];
                    buffer.get(data, 0, index);
                    fireReceiveEvent(keyChannel, data);
                }
            } else {
                for (byte b : data) {
                    i += 1;
                    if (b == 91 || b == 123) {
                        index = i;
                        break;
                    }
                }
                if (index > 0) {
                    data = new byte[index];
                    buffer.get(data, 0, index); // Drain the data that we don't want
                }
            }
        }
        buffer.compact();
    } else if (length < 0) {
        key.cancel();
        closeChannel(keyChannel);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM