C 使用伯克利套接字发送文件

标签 c sockets networking

我正在尝试在用 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 操作系统上,它不受支持。你对我有什么建议吗?

它应该是这样的:

1) 客户端向服务器发送一个缓冲区,宣布它将发送一个包含其名称的文件 - OK

2) 服务器收到此缓冲区并向客户端发送通用 ok 代码 - OK

3) 客户端将文件的大小发送到服务器 - OK

4) 服务器收到此缓冲区并向客户端发送通用 ok 代码 - OK

5) 客户端从文件中读取内容并将其发送到服务器 - 不行

6) 服务器从客户端接收内容并将内容写入文件 - 不正常

最佳答案

这一行,在服务器中,

while(((nread = read(sock_fd,recvBuf,sizeof(recvBuf))) > 0) && remaining_data > 0){

正在尝试先读取,而没有检查 remaining_data >0。结果是所有文件传输后的读取操作。

建议使用 while(remaining_data>0) { select()/read() },其中 select() 具有合理的超时参数并导致退出发生超时时的循环。

关于C 使用伯克利套接字发送文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27784154/

相关文章:

javascript - 如何将 ZeroMQ 套接字与 Ratchet web-socket 库绑定(bind),以便为 php 应用程序实时应用?

c++ - 在同一个盒子上的两个以太网接口(interface)之间发送数据

Java文件上传到Windows共享文件夹并进行身份验证

c - 效率 : 8 arrays vs a multidimensional array

c - 配置文件 glib 中字符串键的引号

sockets - 定义 TCP 套接字选项

mysql - 代理/中继 mysql 连接(以便服务器看起来在本地主机上)

java - Socket 服务器在同一进程上一次仅接受一个连接

c - 使用 define 指令的 Square 不起作用

c - 函数调用后返回的指针值意外更改