iOS protobuf GCDAsyncSocket

时间:2015-03-14 23:49:59

标签: ios netty protocol-buffers gcdasyncsocket cocoaasyncsocket

我正在编写一个小应用程序,需要通过tcp将netobuf消息发送到netty服务器,其中使用了CocoaAsyncSocket / GCDAsyncSocket。

为此,我使用以下代码:

Message_LoginMessageRequest_Builder *msg_tmp_login_build=[Message_LoginMessageRequest builder];
[msg_tmp_login_build setPhoneNumber:input_phone.text];
[msg_tmp_login_build setEmail:input_email.text];
[msg_tmp_login_build setPassword:input_password.text];

Message_Builder *msg_tmp_build=[Message builder];
[msg_tmp_build setType:Message_MessageTypeLoginReq];
[msg_tmp_build setLoginRequest:msg_tmp_login_build.build];

// send the message to the socket: we need to code the stream first
Message *msg=[msg_tmp_build build];
NSMutableData *msg_data=[[NSMutableData alloc] initWithCapacity:[[msg data] length]];
PBCodedOutputStream *coded_output_stream=[PBCodedOutputStream streamWithData:msg_data];
[msg writeToCodedOutputStream:coded_output_stream];
[socket writeData:msg_data withTimeout:-1 tag:Message_MessageTypeLoginReq];

但是,代码总是在writeToCodedOutputStream中收到“空间不足”错误,其中详细的跟踪信息是:writeToCodedOutputStream / writeEnum / writeTag / writeRawVariant32 / writeRawByte / flush。

有任何帮助吗?谢谢!

1 个答案:

答案 0 :(得分:0)

我自己已经找到了答案,通过阅读protobuf的netty编解码器代码,可以在netty / codec / src / main / java / io / netty / handler / codec / protobuf /

中找到

在netty protobuf中,必须在消息正文之前插入描述protobuf消息长度的消息头(稍后请参阅消息正文)。必须通过RawVariant32类型对消息体的长度进行编码。有关更多详细信息,请参阅ProtobufVariant32FrameDecoder.java中的示例,该示例也在下面引用:

/**
 * A decoder that splits the received {@link ByteBuf}s dynamically by the
 * value of the Google Protocol Buffers
 * <a href="http://code.google.com/apis/protocolbuffers/docs/encoding.html#varints">Base
 * 128 Varints</a> integer length field in the message.  For example:
 * <pre>
 * BEFORE DECODE (302 bytes)       AFTER DECODE (300 bytes)
 * +--------+---------------+      +---------------+
 * | Length | Protobuf Data |----->| Protobuf Data |
 * | 0xAC02 |  (300 bytes)  |      |  (300 bytes)  |
 * +--------+---------------+      +---------------+
 * </pre>
 *
 * @see CodedInputStream
 */
public class ProtobufVarint32FrameDecoder extends ByteToMessageDecoder {

    // TODO maxFrameLength + safe skip + fail-fast option
    //      (just like LengthFieldBasedFrameDecoder)

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        in.markReaderIndex();
        final byte[] buf = new byte[5];
        for (int i = 0; i < buf.length; i ++) {
            if (!in.isReadable()) {
                in.resetReaderIndex();
                return;
            }

            buf[i] = in.readByte();
            if (buf[i] >= 0) {
                int length = CodedInputStream.newInstance(buf, 0, i + 1).readRawVarint32();
                if (length < 0) {
                    throw new CorruptedFrameException("negative length: " + length);
                }

                if (in.readableBytes() < length) {
                    in.resetReaderIndex();
                    return;
                } else {
                    out.add(in.readBytes(length));
                    return;
                }
            }
        }

        // Couldn't find the byte whose MSB is off.
        throw new CorruptedFrameException("length wider than 32-bit");
    }
}

欢迎您访问我的个人页面以获取更多详细信息:http://167.88.47.13/?p=254