服务器无法正确读取/打开客户端在C中发送的文件名

服务器无法正确读取/打开客户端在C中发送的文件名,c,file,sockets,client-server,C,File,Sockets,Client Server,我正在用C语言与sockets进行客户机/服务器交互。我试图做的是让客户机请求在服务器上读取一个文件,服务器返回一个文件内容缓冲区,然后客户机打印出该文件 虽然我能够完成服务器向客户机发送文件缓冲区的任务&客户机成功地将其打印出来,但我似乎无法让服务器成功读取客户机发送的文件名 我的意思是: ///This is the structure of the message that gets sent back and forth struct message { int code; //Jus

我正在用C语言与sockets进行客户机/服务器交互。我试图做的是让客户机请求在服务器上读取一个文件,服务器返回一个文件内容缓冲区,然后客户机打印出该文件

虽然我能够完成服务器向客户机发送文件缓冲区的任务&客户机成功地将其打印出来,但我似乎无法让服务器成功读取客户机发送的文件名

我的意思是:

///This is the structure of the message that gets sent back and forth
struct message { 
int code; //Just indicates 1 or 2 for readfile or writefile
int size;
char buffer[256]; //This will hold the filename when client sends readfile request
 };
有效:

char *filename = "test.c";
infile = open(filename, O_RDONLY);
//Send the file and everything back to the client
while( read(sockfd, &msg, sizeof(int) * 2) > 0) {
        if(msg.code == 1) { //Perform a read operation
            int infile, filesize, rr;
            int length;
            char output[256];
            size_t rb = 0;

            while(rb < msg.size) { 
                ssize_t r = read(sockfd, msg.buffer, msg.size - rb);
                if(r < 0) { 
                    error(sockfd, r, msg.buffer);
                    break;
                }
                rb += r;
            }

            msg.buffer[rb] = '\0';  
         //This has been printing out the correct amount
            printf("\nBytes read: %i", rb); 
         //This has also been printing out properly
            printf("\nmsg.buffer: %s", msg.buffer); 

            infile = open(msg.buffer, O_RDONLY);
不起作用:

char *filename = "test.c";
infile = open(filename, O_RDONLY);
//Send the file and everything back to the client
while( read(sockfd, &msg, sizeof(int) * 2) > 0) {
        if(msg.code == 1) { //Perform a read operation
            int infile, filesize, rr;
            int length;
            char output[256];
            size_t rb = 0;

            while(rb < msg.size) { 
                ssize_t r = read(sockfd, msg.buffer, msg.size - rb);
                if(r < 0) { 
                    error(sockfd, r, msg.buffer);
                    break;
                }
                rb += r;
            }

            msg.buffer[rb] = '\0';  
         //This has been printing out the correct amount
            printf("\nBytes read: %i", rb); 
         //This has also been printing out properly
            printf("\nmsg.buffer: %s", msg.buffer); 

            infile = open(msg.buffer, O_RDONLY);
while(读取(sockfd,&msg,sizeof(int)*2)>0){
如果(msg.code==1){//执行读取操作
int填充,文件大小,rr;
整数长度;
字符输出[256];
大小_trb=0;
而(rb

我已编辑以显示我的程序所处的当前状态,但仍然无法工作。以前,我有一个strcpy放置不正确。

您没有检查返回值,该值指示已读取的字节数,-您的消息可能未被完整读取,因此文件名可能会被截断

编辑:
@Amardeep在这里有更好的眼睛看着我-你正在用strcpy(3)腐蚀你的记忆
指向
文件名
指针变量所指向的空格,该变量看起来未初始化。

在您发布的代码中,
文件名
未初始化。您的编译器应该对此发出警告。如果未初始化,则说明您没有正确调用它;使用
gcc
,至少执行
gcc-O-Wall

如果使用
strcpy
,则还需要为文件名分配内存。在简单的程序中,此步骤不是必需的;如果继续从客户端读取后需要记住文件名,则制作副本会很有用。
strdup
函数将内存分配与字符串复制结合在一起,在这里很合适

您需要检查所有系统调用的返回值。
read的返回值告诉您读取了多少字节。
read的调用(fd,buf,n)
允许返回少于
n
字节,如果操作系统喜欢。如果收到的字节少于预期,则在循环中调用
read
。是的,几乎所有调用
read
的程序都在循环中调用它,这是一种基本的Unix/POSIX习惯用法。
fread
函数可以为您实现这一功能,如果您可以将其安装进去的话

用于检查
msg.code
msg.size
有效性的代码缺失。由于您在
msg.buffer
中分配了256个字节,因此必须将
msg.size
限制为255

是的,赋值
msg.buffer[msg.size]='\0'
是必需的,因为
open
需要在名称的末尾添加
'\0'
字符(这就是它如何知道名称的结尾)


我想也许strcpy是合适的


每当你在指针附近时(在C语言中大部分时间都是这样),你需要仔细考虑你在做什么,指针指向哪里,以及是否有足够的空间放你想放的东西。C是一种无情的语言;到处扔指针就像到处扔箭头一样危险。绘制图表!有两种C程序员:绘制图表的人ms在白板上、纸上、沙子或其他介质中;以及那些在头脑中绘制图表的人(第三类人仍在试图弄清楚为什么他们打印
1+1
的程序正在打印
3
,我看到第二个条在下一行。我将该行打断,并在结尾处用空字符重写了它

我也改为fopen和freads/writes。我在file语句的开头添加了
/
,但我怀疑这是必要的。这只是我以前的一次尝试。现在看起来像这样:

            size_t rb = 0;
            FILE* file;
            char filename[256];
            while(rb < msg.size) { 
                ssize_t r = read(sockfd, filename, msg.size - rb);
                if(r < 0) { 
                    error(sockfd, r, msg.buffer);
                    goto end;
                }
                rb += r;
            }
            if(strlen(filename) > 253) { 
                error(sockfd, rb, msg.buffer);
                goto end;
            }
            strcpy(msg.buffer, "./");
            strcat(msg.buffer, filename);
            msg.buffer[rb + 1] = '\0';

            file = fopen(msg.buffer, "r");
            if(file == NULL) {
                error(sockfd, rb, msg.buffer);
                printf("Error opening file %s: %s\n", msg.buffer,strerror(errno));
                fflush(stdout);
                goto end;
            }
size\u t rb=0;
文件*文件;
字符文件名[256];
而(rb253){
错误(sockfd、rb、msg.buffer);
转到终点;
}
strcpy(msg.buffer,“./”);
strcat(msg.buffer,文件名);
msg.buffer[rb+1]='\0';
file=fopen(msg.buffer,“r”);
if(file==NULL){
错误(sockfd、rb、msg.buffer);
printf(“打开文件%s时出错:%s\n”,msg.buffer,strerror(errno));
fflush(stdout);
转到终点;
}

感谢所有帮助过我的人。我学到了很多(gdb特别有用——我以前从未使用过它)

此外,您的strcpy()正在写入未初始化的指针filename。谢谢,但我将发送到服务器的缓冲区返回给客户端,它(似乎)是一样的:用法:输入: