我正在编写一个小型客户端/服务器C程序。客户端中的一个函数将用于询问服务器中某个目录中所有常规文件的名称。服务器将通过TCP以字符数组的形式返回文件名。我的程序有很多选择,可以单独运行任意次数,也可以轻松切换。当我试图运行函数来获取文件名时,我会遇到分段错误,不知道为什么。我已经在下面粘贴了我的客户端和服务器代码。
服务器:
void dir_details(int socket) {
//Set up appropriate variables
char StringArray[1024];
struct dirent *de;
struct stat st = {0};
//If the upload directory doesn't exist, create it
if (stat("upload", &st) == -1) {
mkdir("upload", 0777);
}
//Opening the upload directory to be read
DIR *dr = opendir("upload");
if (dr == NULL) {
printf("Could not open directory.");
}
//Add each file name to a char array
while ((de = readdir(dr)) != NULL) {
strcat(StringArray, de->d_name);
strcat(StringArray, "n");
}
closedir(dr);
size_t n = sizeof(StringArray);
//Send the char array back to the client
writen(socket, (unsigned char *) &n, sizeof(size_t));
writen(socket, (unsigned char *) StringArray, n);
strcpy(StringArray, "");
free(de);
}
客户:
void dir_details(int socket) {
//Set up char array to be received form the server
char dirdetails[5000];
size_t k;
//Receive char array from the server
readn(socket, (unsigned char *) &k, sizeof(size_t));
readn(socket, (unsigned char *) &dirdetails, k);
//Print the array to the client
printf("%sn", dirdetails);
}
仔细阅读读目录(3(。在实践中,struct dirent
的最后一个成员d_name
可以表现为一个灵活的数组成员,即使它可能没有被确切地记录为这样。
您的StringArray
可能存在缓冲区溢出(而且您检查得不够仔细(。你忘了把它归零(至少用memset(StringArray, 0, sizeof (StringArray));
…(
当然,你误解了malloc。它可能会失败,你总是需要利用它的结果。阅读更多关于C动态内存分配的信息。
阅读如何调试小程序。编译时使用所有警告和调试信息,如果使用GCC,则使用gcc -Wall -Wextra -g
。
花几天时间阅读更多关于基本C编程的内容。阅读一些C教程。查看一些C参考网站。如果有疑问,请在阅读了一些关于C编程的好教程后,查看C11标准n1570。研究小型免费软件程序的源代码以获得灵感。
在提高了你的基本C编程技能之后,阅读一些关于Linux编程的内容,例如ALP。
销毁你的无意义程序(它太bug了,不值得改进或尝试挽救它(一旦你提高了C编程水平,就从头开始重新编写程序使用一个好的版本控制系统(我推荐git(,并进行一些非常迭代和增量的开发(写一两打行,编译它们时带有所有警告,将它们改进为没有警告,用GDB调试器测试它们,然后将它们提交到版本控制中,然后重复所有操作(。仔细阅读您正在使用的每个函数的文档(例如man
页面,如Read(2(、syscalls(2(,errno(3(、printf(3(等(
注:。在触摸键盘之前,你可能应该花至少一周的时间阅读。实际上,我建议阅读SICP(一本优秀的编程入门,它不使用C,但教授非常重要和相关的概念(