发送一个内部带有 char 指针的结构?

发布于 2024-10-07 14:39:16 字数 403 浏览 6 评论 0原文

我试图将一个数据包从我的 C 程序发送到我的 Delphi 程序,数据的大小是可变的,如果我使用 char Data[1024];即使数据是 3 个字节,它也会发送 1024 个字节,如果数据大于 1024,它不会发送全部:(

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

im trying to send a packet from my C program to my Delphi program, the data is variable in size, and if i used char Data[1024]; it will send 1024 bytes even if the data is 3 bytes, and if the data is larger than 1024 it wont send all of it :(

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);

thanks
oh, btw, im using gcc under windows

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

兔姬 2024-10-14 14:39:17

接收方(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);

The receiving side (Delphi) should be made aware of the size of the data by a method agreed upon by the sender and the receiver (i.e, you should implement a simple protocol for data transfer). As you are transferring an entire struct, your protocol should also take care of specifying types. The easiest solution is to use a textual data interchange format like XML or 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);
雪若未夕 2024-10-14 14:39:17

实际上,您想要做的是发送消息的短标头,后跟可变长度数据。标头应至少包含其后的数据的大小。一个简单的实现是这样的:

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,但是要解析数据包,你需要做相反的事情。读取标头以获取数据的大小,然后将这么多数据从套接字读取到新分配的缓冲区中。

Really, what you want to do is send a short header for your message followed by the variable-length data. The header should contain at least the size of the data that follows it. A simple implementation goes something like this:

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);
}

I don't know Delphi, but to parse the packet, you do the opposite. Read the header to get the size of the data, then read that much data out of the socket into a newly-allocated buffer.

待天淡蓝洁白时 2024-10-14 14:39:17

您需要指定发送数据的正确长度。使用:

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));

You need to specify the correct length of the data sent. Using:

sizeof(struct Packet)

as you have done is wrong and will only give you 8 bytes, 4 bytes for the int and 4 bytes for the char*, on a 32 bit system.

Note that

char*

is a different type from a character array. It's a pointer to a char. For example, the results of sizeof here are different:

char arr[1024];
char* pc = arr;
printf("%d, %d", sizeof(pc), sizeof(arr));
我ぃ本無心為│何有愛 2024-10-14 14:39:16

将数据包封装在单个块中的一个老技巧是在数据包末尾使用长度为 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 作为单个对象传递,其中包含一个分配调用和一个释放调用。

An old trick for encapsulating the packet in a single block is to use an array of length 1 at the end of the Packet.

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);
}

Note how this means we have a single send() call, and in general can pass a Packet around as a single object, with one allocation call and one deallocation call.

疏忽 2024-10-14 14:39:16

您应该为您的结构实现序列化方法。
您现在尝试发送它的方式永远不会起作用,因为您实际上并没有发送 char* 的内容,而是发送指针本身。这只是一个内部地址,接收程序将不知道您想要完成什么。

You should implement a serialization method for your struct.
The way you are trying to send it now is never going to work since you are not actually sending the contents of your char*, you are sending the pointer itself. That is only an internal address and the receiving program will have no idea what you are trying to accomplish.

左耳近心 2024-10-14 14:39:16

指针是对内存地址的引用,因此您当前发送的是地址而不是内容。因此,您需要更改它以发送实际字符数组。
您需要在实际字符数组之前发送大小信息(首选)或定义字符数组结束符号

A pointer is a reference to a memory address, so you are currently sending the address instead of the content. Thus you need to change it to send an array of actual characters.
You need to send either the size information (prefered) before the actual array of chars or define an end of character array sign

一曲琵琶半遮面シ 2024-10-14 14:39:16

您的代码不正确 - 当您像这样直接发送结构时,您发送的是一个指针(Data_的地址),而不是实际的字符串。您有两种选择:

  1. 正如您已经提到的,在结构内部使用固定大小的数组。

  2. 通过套接字手动发送长度和实际字符串数据,例如:


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);

Your code is incorrect -- when you send the structure directly like that, what you're sending is a pointer (address of Data_), not the actual string. You have two choices:

  1. As you already mentioned, use a fixed-size array inside the structure.

  2. Manually send the length followed by the actual string data over the socket, for example:


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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文