Netty Bytebuf writeShort无法正确发送给C客户端

时间:2017-11-07 03:07:53

标签: tcp netty

我试图搜索整个谷歌以获得正确的问题。但我仍然没有得到什么。这里的问题是:    我有一个用C语言编写的tcp客户端。将二进制流发送到Netty的tcp服务器很简单。首先,简单一点,tcp服务器只回显从服务器到客户端的整个数据。但是使用Bytebuf" writeShort"是很奇怪的。进入buff,客户端将edian从BIG-endian更改为Small-edian。这样将0x007b转换为0x7b00。我不知道这是不是一个bug。遵循以下代码:    c tcp客户端:

#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>


#define HALO_HEADER ("halohalo")
#define DATA_STILL_LEN (14U)

typedef struct {
    unsigned char headerId[8];
    short package_len;
    short opType;
    short res;
    unsigned char data[100];
} halo_transfer_t;

void printfHaloStructBuf(char* table, halo_transfer_t *packet)
{ 
    int i = 0;
    int dataLen = 0;
    printf("包头Id: %s\n", packet->headerId);
    printf("包大小: %d\n", packet->package_len);
    printf("操作码: %d\n", packet->opType);
    printf("附加数据实际有效长度: %d\n",packet->package_len - DATA_STILL_LEN);
    printf("附加数据:\n");
    dataLen = packet->package_len - DATA_STILL_LEN;

    if(dataLen < 0)
        return;

    for(i=0; i<dataLen;i++) {
        if((i!=0)&&(i%16==0))
            printf("\n");
        printf("0x%x, ", packet->data[i]);
    }
    printf("\n");
}

void setUpPackageHeaderId(halo_transfer_t *package)
{
    memcpy(package->headerId, HALO_HEADER ,sizeof(package->headerId));
}

void setUpPackage(uint32_t package_len, uint8_t* data, halo_transfer_t *out)
{
    int i = 0;

    memset(out, 0, sizeof(halo_transfer_t));
    setUpPackageHeaderId(out);  //头部
    out->package_len = package_len;
    out->opType = 123;
    out->res = 0;
    for(int i = 0; i < 100; ++i) {
        out->data[i] = i;
    }
}

#define BUFFSIZE 1024 
void Die(char *mess) { perror(mess); exit(1); }
int main(int argc, char *argv[]) {
    int sock;
    struct sockaddr_in echoserver;
    char buffer[BUFFSIZE];
    unsigned int echolen;
    int received = 0;

    if (argc != 3) {
        fprintf(stderr, "USAGE: TCPecho <server_ip> <port>\n");
        exit(1);
    }
    /* Create the TCP socket */
    if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
        Die("Failed to create socket");
    }


    /* Construct the server sockaddr_in structure */
    memset(&echoserver, 0, sizeof(echoserver));       /* Clear struct */
    echoserver.sin_family = AF_INET;                  /* Internet/IP */
    echoserver.sin_addr.s_addr = inet_addr(argv[1]);  /* IP address */
    echoserver.sin_port = htons(atoi(argv[2]));       /* server port */
    /* Establish connection */
    if (connect(sock,
                (struct sockaddr *) &echoserver,
                sizeof(echoserver)) < 0) {
        Die("Failed to connect with server");
    }

    halo_transfer_t send_data;
    memset(&send_data, 0x00, sizeof(halo_transfer_t));

    unsigned char data[100] = {'\0'};

    /* Send the word to the server */
    setUpPackage(114, data, &send_data);
    printfHaloStructBuf("#####发送数据####\n",&send_data);
    //send(sock, (char*)&send_data, send_data.package_len, 0);
    int rc = write(sock, (char*)&send_data, send_data.package_len);
    if(rc < 0) {
        perror("Client-write() error");
        int temp = 0;
        int length = sizeof(int);
        rc = getsockopt(sock, SOL_SOCKET, SO_ERROR, &temp, &length);
        if(rc == 0) {
            /* Print out the asynchronously received error. */
            perror("SO_ERROR was");
        }
        close(sock);
        exit(-1);
    } else {
        printf("Client-write() is OK\n");
        printf("String successfully sent lol!\n");
    }

    /* Receive the word back from the server */
    int totalcnt = 0;
    while(totalcnt < send_data.package_len) {

        /* Wait for the server to echo the */
        /* string by using the read() function. */
        /***************************************/
        /* Read data from the server. */
        rc = read(sock, &buffer[totalcnt], send_data.package_len - totalcnt);
        printf("Receive from server's count: %d\n", rc);
        if(rc < 0) {
            perror("Client-read() error");
            close(sock);
            exit(-1);
        } else if (rc == 0) {
            printf("Server program has issued a close()\n");
            close(sock);
            exit(-1);
        } else
            totalcnt += rc;
    }
    printf("Client-read() is OK\n");
    printfHaloStructBuf("Recv from server", (halo_transfer_t*)&buffer);
    //printf("Echoed data from the server len =%d, cnt = %s\n", strlen(buffer), buffer);

    fprintf(stdout, "\n");
    close(sock);
    exit(0);
}   

netty的tcp服务器:

原:

 public class Proto implements Serializable{
        /**
         * 
         */
        private static final long serialVersionUID = 1L;
        private byte[] headerId; //8 byte
        private short package_len;//2 byte
        private short opType; // 2 byte
        private short res;
        private byte[] data; // variable

        public Proto(byte[] headerId, short package_len, short opType, byte[] data) {
            this.headerId = headerId;
            this.package_len = package_len;
            this.opType = opType;
            this.res = 0;
            this.data = data;
        }

        public short getPackage_len() {
            return package_len;
        }

        public void setPackage_len(short package_len) {
            this.package_len = package_len;
        }

        public short getOpType() {
            return opType;
        }

        public void setOpType(short opType) {
            this.opType = opType;
        }

        public byte[] getData() {
            return data;
        }

        public void setData(byte[] data) {
            this.data = data;
        }

        public byte[] getHeaderId() {
            return headerId;
        }

        public void setHeaderId(byte[] headerId) {
            this.headerId = headerId;
        }
        @Override
        public String toString() {
            String strHeaderId = new String(headerId);
            //String strData = new String(data);

             return String.format("[headerId=%s,package_len=%d, opType=%x,content=%s]",
                     strHeaderId, package_len, opType, Utils.bytesToHexString(data));
        }

        public short getRes() {
            return 0;
        }

        public void setRes(short res) {
            this.res = res;
        }

    }

解码:

public class ProtoDecoder扩展了ByteToMessageDecoder {

@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
    // TODO Auto-generated method stub

    if(in.readableBytes() >= 14) {

        //System.out.println("1-->Decode is running, in length " + in.readableBytes());
        byte[] haloId = new byte[8];
        short package_len = 0;
        in.getBytes(0, haloId);
        package_len = in.getByte(8);
        int data_len = package_len - 14;
        //System.out.println("Decode is running, package len " + in.readableBytes());
        short opType = in.getByte(10);
        short res = in.getByte(12);
        byte[] data = new byte[data_len];
        in.getBytes(14, data);
        System.out.println(String.format("Decode is running, headerId=%s, package_len=%d, opType=%d, data=%s\n",
                Utils.bytesToHexString(haloId), package_len, opType, Utils.bytesToHexString(data)));

        Proto p = new Proto(haloId, package_len, opType, data);
        out.add(p);

    } else {
        return;
    }
}

}

编码:

public class ProtoEncoder extends MessageToByteEncoder<Proto> {

    @Override
    protected void encode(ChannelHandlerContext ctx, Proto msg, ByteBuf out) throws Exception {
        // TODO Auto-generated method stub
        if (msg == null) {
            throw new Exception("The encode message is null");
        }
        //System.out.print("Encode msg:  " + msg.toString());;

        ByteBuf buf = Unpooled.buffer(1024);
        out.writeBytes(msg.getHeaderId());
        out.writeShort(msg.getPackage_len());
        out.writeShort(msg.getOpType());
        out.writeShort(msg.getRes());
        out.writeBytes(msg.getData());

        byte[] haloId = new byte[8];
        byte[] data = new byte[msg.getPackage_len()];

        System.out.println(String.format("haloid = %s, package_len = %d, opType=%d, res = %d, data=%s", out.getBytes(0, haloId)  
                ,out.getByte(8) 
        ,out.getByte(10) ,
        out.getByte(12) 
        ,out.getBytes(14, data)));

    }
}
非常感谢!

1 个答案:

答案 0 :(得分:0)

您的协议和c impl可能需要LITTLE_ENDIAN。如果是这种情况,请使用:

byteBuf.writeShortLE(...)