我试图在用c。
编写的客户端 - 服务器应用程序上发送文件客户端应该上传文件,服务器应该接收文件。 客户方:
if(fstat(fd,&file_stat) < 0){
perror("Fstat error");
return -1;
}
FILE *filepointer = fopen(filename,"rb");
if(filepointer == NULL){
perror("Opening file error");
return -1;
}
strcat(sendbuf,"8"); // option number
strcat(sendbuf,client_account.user); //user who is sending a file
strcat(sendbuf,"p1.txt"); // file name
printf("sendbuf : %s\n",sendbuf );
if(write(sock_fd,sendbuf,strlen(sendbuf)) < 0 ){
perror("Writing error");
return -1;
}
/* Check server's answer */
if((nread = read(sock_fd,buffer,sizeof(buffer))) < 0){
perror("Reading error");
return -1;
}
buffer[nread] = '\0';
printf("Buffer : %s : %d",buffer,atoi(buffer));
if(atoi(buffer) != GENERIC_OK){
printf("Error occurred\n");
return -1;
}
sprintf(file_size,"%lld",file_stat.st_size);
/* Writing file size */
if((nwritten = write(sock_fd,file_size,sizeof(file_size))) < 0){
perror("Writing error");
return -1;
}
memset(buffer,0,sizeof(buffer));
/* Check second server's answer */
if((nread = read(sock_fd,buffer,sizeof(buffer))) < 0){
perror("Reading error");
return -1;
}
buffer[nread] = '\0';
printf("Buffer : %s : %d",buffer,atoi(buffer));
if(atoi(buffer) != GENERIC_OK){
printf("Error occurred\n");
return -1;
}
while(1){
nbytes = fread(sendbuf,1,sizeof(sendbuf),filepointer);
/* There are bytes to send */
printf("Sendbuf : %s \n" , sendbuf);
if(nbytes > 0){
write(sock_fd,sendbuf,nbytes);
}
if(nbytes < 256){
if(feof(filepointer) || ferror(filepointer))
break;
}
}
服务器端:
... first buffer is received well ...`
/* WRITE TO CLIENT TO CONTINUE */
if(write(sock_fd,"500",strlen("500")) < 0){ /*GENERIC OK*/
perror("Writing error");
return -1;
}
memset(recvBuf,0,sizeof(recvBuf));
/*RECEIVING FILE SIZE */
if((nread = read(sock_fd,buffer,sizeof(buffer)))< 0){
perror("Reading error");
return -1;
}
buffer[nread] = '\0';
file_size = atoi(buffer);
printf("file size : %d\n",file_size);
if((fd = open(filename, O_CREAT | O_RDWR | O_TRUNC, S_IRWXU)) < 0){
perror("File opening error"); /* file already exists */
}
recv_file = fopen(filename,"wb");
if(recv_file == NULL){
perror("Opening error");
return -1;
}
remaining_data = file_size;/*i think processes are blocking on while loops*/
while(((nread = read(sock_fd,recvBuf,sizeof(recvBuf))) > 0) && remaining_data > 0){
recvBuf[nread] = '\0';
printf("%d bytes received : %s \n",nread,recvBuf);
fwrite(recvBuf,1,nread,recv_file);
remaining_data -= nread;
}
if(nread < 0){
perror("Reading error");
}
我尝试使用sendfile
功能,但我在Mac OS上使用它并且不受支持。你有什么建议吗?
它应该是这样的:
1)客户端向服务器发送缓冲区,宣布它将发送一个带有其名称的文件 - 确定
2)服务器收到此缓冲区并向客户端发送通用的ok代码 - 确定
3)客户端将文件大小发送到服务器 - 确定
4)服务器接收此缓冲区并向客户端发送通用的ok代码 - 确定
5)客户端从文件中读取内容并将其发送到服务器 - 不行
6)服务器从客户端接收内容并将内容写入文件 - 不行
答案 0 :(得分:1)
此代码:
if((fd = open(filename, O_CREAT | O_RDWR | O_TRUNC, S_IRWXU)) < 0){
perror("File opening error"); /* file already exists */
}
recv_file = fopen(filename,"wb");
if(recv_file == NULL){
perror("Opening error");
return -1;
}
在服务器中打开输出文件两次,没有干预close()
。这可能不是我们所需要的。
答案 1 :(得分:1)
这一行,在服务器中,
while(((nread = read(sock_fd,recvBuf,sizeof(recvBuf))) > 0) && remaining_data > 0){
首先尝试阅读,但未检查remaining_data >0
。结果是在传输完所有文件后进行读取操作。
建议使用while(remaining_data>0) { select()/read() }
,其中select()
具有合理的超时参数,并在超时发生时导致循环退出。
答案 2 :(得分:0)
我认为您遗漏了一些相关代码,但很可能关键问题出现在服务器的while
条件中:
while(((nread = read(sock_fd,recvBuf,sizeof(recvBuf))) > 0) && remaining_data > 0){
请注意,总是尝试读取数据,即使它已经读取了预期的字节数。如果客户端保持连接打开(可能它等待来自服务器的响应),则不会检测到EOF条件,并且您有死锁。
交换条件的顺序应解决该问题,至少对于行为良好的客户端。但是,请注意,即使进行了此更改,如果客户端发送的字节数少于其承诺的数量,仍然可以获得死锁,但仍保持连接打开状态。 恶意客户端可能会故意展示该行为以对您的服务器执行DoS。
答案 3 :(得分:0)
另外,'read(sock_fd,buffer,sizeof(buffer)',后跟'buffer [nread] ='\ 0';'如果完整'sizeof(buffer)'字节是','将缓冲区溢出1接收。
'file_size = atoi(buffer)' - 由于您不知道是否已收到整个缓冲区,因此无法保证正常工作。
同样的字节序问题。