struct Packet
{
int State_;
char *Data;
};
struct Packet MyPacket;
MyPacket.Data = (char *) calloc(8, sizeof(char));
memcpy(MyPacket.Data, "thi sis", 8);
send(Socket, MyPacket, (int)sizeof(struct Packet), 0);
感谢 哦,顺便说一下,我在windows下使用gcc
答案 0 :(得分:5)
您应该为您的struct实现序列化方法。 您现在尝试发送它的方式永远不会起作用,因为您实际上并未发送char *的内容,而是您自己发送指针。这只是一个内部地址,接收程序将不知道你想要完成什么。
答案 1 :(得分:5)
将数据包封装在单个块中的一个老技巧是在数据包末尾使用长度为1的数组。
struct Packet
{
unsigned packetLengthInBytes_;
/* All the fixed fields in the packet */
int State_;
/* Generic data in the packet - of actual length given by packetDataLength(packet) */
char Data[1];
};
unsigned packetDataLength(Packet* packet)
{
return packet->packetLengthInBytes_ - (sizeof(Packet) - 1);
}
Packet* createPacketFromData(const char* data, unsigned dataSize)
{
unsigned packetSize = sizeof(Packet) + dataSize - 1;
Packet* packet = (Packet*)malloc(packetSize);
packet->packetLengthInBytes_ = packetSize;
memcpy(packet->Data, data, dataSize);
return packet;
}
int sendData(int sock, const char* data, unsigned dataSize)
{
Packet* packet = createPacketFromData(data, dataSize);
/* [ Yes, think about endian issues.] */
send(sock, packet, packet->packetLengthInBytes_, 0);
free(packet);
}
注意这意味着我们有一个send()调用,并且通常可以将一个Packet作为单个对象传递,只有一个分配调用和一个释放调用。
答案 2 :(得分:1)
接收方(Delphi)应通过发送方和接收方商定的方法了解数据的大小(即,您应该实现一个简单的数据传输协议)。当您传输整个struct
时,您的协议也应该注意指定类型。最简单的解决方案是使用XML或JASON等文本数据交换格式:
// Code to demonstrate the idea, may not compile.
struct Packet MyPacket;
MyPacket.State_ = 0;
MyPacket.Data = (char *) calloc(8, sizeof(char));
memcpy(MyPacket.Data, "thi sis", 8);
const char* packetXml = PacketToXml();
/*
packetXml =
<Packet>
<State>0</State>
<Data>thi sis</Data>
</Packet>
*/
size_t len = strlen(packetXml);
send(Socket, (char*)&len, sizeof(size_t), 0);
send(Socket, packetXml, len, 0);
答案 3 :(得分:1)
指针是对内存地址的引用,因此您当前正在发送地址而不是内容。因此,您需要更改它以发送一组实际字符 您需要在实际的字符数组之前发送大小信息(首选)或定义字符数组符号的结尾
答案 4 :(得分:1)
您的代码不正确 - 当您直接发送结构时,您发送的是指针(Data_
的地址),而不是实际的字符串。你有两个选择:
正如您已经提到的,在结构中使用固定大小的数组。
手动发送长度,然后通过套接字发送实际字符串数据,例如:
int length = 8;
char *data = (char *) calloc(length, sizeof(char));
memcpy(data, "thi sis", 8);
send(Socket, &length, sizeof(length), 0);
send(Socket, data, length, 0);
答案 5 :(得分:1)
实际上,您要做的是为您的消息发送一个短标题,然后是可变长度数据。标头应至少包含其后面的数据大小。一个简单的实现是这样的:
struct Packet {
int State_;
char *Data;
};
struct PacketHeader {
uint32_t state;
uint32_t len;
};
int send_packet(int sock, struct Packet *pkt)
{
struct PacketHeader hdr;
int len = strlen(pkt->Data); /* If Data is a C string */
hdr.state = htonl(pkt->State_);
hdr.len = htonl(len);
send(sock, &hdr, sizeof(hdr), 0);
send(sock, pkt->data, len, 0);
}
我不知道Delphi,但要解析数据包,你会反其道而行之。读取标头以获取数据的大小,然后从套接字中读取那么多数据到新分配的缓冲区中。
答案 6 :(得分:0)
您需要指定发送数据的正确长度。使用:
sizeof(struct Packet)
正如你所做的那样是错误的,在32位系统上只给你8个字节,4个字节用于int和4个字节用于char *。
请注意
char*
是与字符数组不同的类型。它是一个指向char的指针。例如,sizeof的结果不同:
char arr[1024];
char* pc = arr;
printf("%d, %d", sizeof(pc), sizeof(arr));