我试图搜索整个谷歌以获得正确的问题。但我仍然没有得到什么。这里的问题是: 我有一个用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)));
}
}
非常感谢!
答案 0 :(得分:0)
您的协议和c impl可能需要LITTLE_ENDIAN
。如果是这种情况,请使用:
byteBuf.writeShortLE(...)