通过TCP发送结构中未知长度字符串的智能方法?(C、Linux)

通过TCP发送结构中未知长度字符串的智能方法?(C、Linux),c,networking,tcp,struct,char,C,Networking,Tcp,Struct,Char,我正在Linux上用C实现一个简单的服务器/客户机。 比方说,作为一个客户机,我想询问服务器上是否有一个特定的文件。 我希望能够将我的查询发送到结构中的服务器(我更熟悉此操作的问题,但这是家庭作业) 我的问题是,在使用结构时,我无法在高级中为文件名分配内存。 因此,表单的结构: struct{ int operation; char *fileName; long fileSize; }; 对我没有帮助,因为即使我为文件名分配内存,sizeof(struct)也保持不变(sizeof(char

我正在Linux上用C实现一个简单的服务器/客户机。 比方说,作为一个客户机,我想询问服务器上是否有一个特定的文件。 我希望能够将我的查询发送到结构中的服务器(我更熟悉此操作的问题,但这是家庭作业)

我的问题是,在使用结构时,我无法在高级中为文件名分配内存。 因此,表单的结构:

struct{
int operation;
char *fileName;
long fileSize;
};
对我没有帮助,因为即使我为文件名分配内存,
sizeof(struct)
也保持不变
(sizeof(char*)+sizeof(fileSize))
,所以我无法将其发送到服务器

希望我在这里说清楚。。。我的问题是如何使用struct将未知大小的字符串发送到服务器。 (一个选项是以高级格式发送文件大小,然后发送该大小的char*,但我不想这样做)


谢谢

您可以将发送分成3个命令-操作(int)、文件名长度(int)、文件名(0..n个字符)


如果您的家庭作业要求您使用单个send命令,请为所有三个命令分配足够大的缓冲区,然后复制到其中。

您可以将send命令拆分为3个命令-操作(int)、文件名长度(int)、文件名(0..n个字符)


如果您的家庭作业要求您使用一个send命令,请为所有三个命令分配一个足够大的缓冲区,然后复制到其中。

我认为,在您的情况下,没有比先发送文件长度,然后发送文件名更好的解决方案了

您也可以使用如下结构(无需预先发送大小)

但这是一个相当脆弱的解决方案。您的文件名可能比

足够长的文件名


缓冲区大小,这将导致一些严重的问题。

我认为在您的情况下,没有比先发送文件长度,然后发送文件名更好的解决方案了

您也可以使用如下结构(无需预先发送大小)

但这是一个相当脆弱的解决方案。您的文件名可能比

足够长的文件名


缓冲区大小,这将导致一些严重的问题。

您不希望跨线路将结构从一台机器发送到另一台机器,以及潜在的endian问题。您还可能面临一个问题,即一台机器上的结构布局可能与不同平台上的结构布局不同

你想要的是:

  Client side                                     Server side
将结构转换为数据流---(1)--->将数据流转换为结构

然后,您只需为数据流的语法定义契约(1) 定义文件名前加长度似乎是合理的 或者发送以null结尾的文件名


正如codewarrior所说,硬连接最大文件名很少是一个好主意。

您不希望通过连接将结构从一台机器发送到另一台机器,以及潜在的endian问题。您还可能面临一个问题,即一台机器上的结构布局可能与不同平台上的结构布局不同

你想要的是:

  Client side                                     Server side
将结构转换为数据流---(1)--->将数据流转换为结构

然后,您只需为数据流的语法定义契约(1) 定义文件名前加长度似乎是合理的 或者发送以null结尾的文件名


正如codewarrior所说,硬连接最大文件名很少是个好主意。

我不确定是否理解您的问题。但这里有一种方法仍然可以使用struct并在最后打包文件名。这里重要的是,需要malloc足够的字节来存储结构+隐藏在结构之后的文件名数据

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

typedef struct
{
    // put any data you want here
    // ...
    size_t fileNameLength;
    char fileName[0]; // fake array, used to access extra bytes allocated after the struct
} FileInfo;

int main (int argc, char **argv)
{
    FileInfo *fi = NULL;

    // The fake array has size 0 !
    printf ("sizeof FileInfo is %d\n", sizeof (FileInfo));

    // let's suppose you've guessed your filename
    char filename[] = "homework.txt";
    size_t filename_length = strlen (filename); // this is the length with no NULL byte
    printf ("filename length (without NULL byte) is %d\n", filename_length);

    fi = malloc (sizeof(FileInfo) + filename_length);
    fi->fileNameLength = filename_length;
    memcpy (&fi->fileName, filename, filename_length);

    printf ("filename is %.*s\n", fi->fileNameLength, fi->fileName);

    // To send your struct + filename, just use the same address (fi),
    // but don't use as length sizeof (FileInfo), but this length:
    size_t struct_total_length = sizeof (FileInfo) + fi->fileNameLength;
    return 0;
}
#包括
#包括
#包括
类型定义结构
{
//把你想要的数据放在这里
// ...
大小\u t文件名长度;
char fileName[0];//伪数组,用于访问在结构之后分配的额外字节
}文件信息;
int main(int argc,字符**argv)
{
FileInfo*fi=NULL;
//伪数组的大小为0!
printf(“sizeof FileInfo是%d\n”,sizeof(FileInfo));
//假设您猜到了文件名
char filename[]=“家庭作业.txt”;
size\u t filename\u length=strlen(filename);//这是没有空字节的长度
printf(“文件名长度(无空字节)为%d\n”,文件名\u长度);
fi=malloc(sizeof(FileInfo)+文件名长度);
fi->fileNameLength=文件名\u长度;
memcpy(&fi->fileName,fileName,fileName\u length);
printf(“文件名为%.*s\n”,fi->fileNameLength,fi->filename);
//要发送struct+文件名,只需使用相同的地址(fi),
//但不要用作长度sizeof(FileInfo),但此长度:
size\u t struct\u total\u length=sizeof(FileInfo)+fi->fileNameLength;
返回0;
}

我不确定是否理解您的问题。但这里有一种方法仍然可以使用struct并在最后打包文件名。这里重要的是,需要malloc足够的字节来存储结构+隐藏在结构之后的文件名数据

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

typedef struct
{
    // put any data you want here
    // ...
    size_t fileNameLength;
    char fileName[0]; // fake array, used to access extra bytes allocated after the struct
} FileInfo;

int main (int argc, char **argv)
{
    FileInfo *fi = NULL;

    // The fake array has size 0 !
    printf ("sizeof FileInfo is %d\n", sizeof (FileInfo));

    // let's suppose you've guessed your filename
    char filename[] = "homework.txt";
    size_t filename_length = strlen (filename); // this is the length with no NULL byte
    printf ("filename length (without NULL byte) is %d\n", filename_length);

    fi = malloc (sizeof(FileInfo) + filename_length);
    fi->fileNameLength = filename_length;
    memcpy (&fi->fileName, filename, filename_length);

    printf ("filename is %.*s\n", fi->fileNameLength, fi->fileName);

    // To send your struct + filename, just use the same address (fi),
    // but don't use as length sizeof (FileInfo), but this length:
    size_t struct_total_length = sizeof (FileInfo) + fi->fileNameLength;
    return 0;
}
#包括
#包括
#包括
类型定义结构
{
//把你想要的数据放在这里
// ...
大小\u t文件名长度;
char fileName[0];//伪数组,用于访问在结构之后分配的额外字节
}文件信息;
int main(int argc,字符**argv)
{
FileInfo*fi=NULL;
//伪数组的大小为0!
printf(“sizeof FileInfo是%d\n”,sizeof(FileInfo));
//假设您猜到了文件名
char filename[]=“家庭作业.txt”;
size\u t filename\u length=strlen(filename);//这是没有空字节的长度
printf(“文件名长度(无空字节)为%d\n”,文件名\u长度);
fi=malloc(sizeof(FileInfo)+文件名长度);
fi->fileNameLength=文件名\u长度;
memcpy(&fi->fileName,fileName,fileName\u length);
printf(“文件名为%.*s\n”,fi->fileNameLength,fi->filename);
//要发送struct+文件名,只需使用相同的地址(fi),
//但是唐
uint32_t net_length = htonl(strlen(filename)+1);  // include trailing NUL
send(socket, &net_length, 4);
send(socket, filename, strlen(filename));
char buffer[whatever]
until have at least 4 bytes in buffer {
  got = recv(socket, buffer+have, sizeof(buffer)-have);
  have += got
}
uint32_t length = ntohl(*(uint32_t*)buffer)
until have at least length+4 bytes in buffer {
  got = recv(socket, buffer+have, sizeof(buffer)-have);
  have += got
}
char* filename = &buffer[4]