m0_62667564 2023-06-08 21:14 采纳率: 84.8%
浏览 41
已结题

网络编程有关文件传输的问题

网络编程 文件传输
一个功能是输入ls,显示服务端当前目录下所有文件,另一个功能是输入 download +文件名,将该文件从服务器传到客户端,为什么运行时不管输入什么命令都是服务端输出bad file descriptor,客户端输出Unsupported command,这是为什么?怎么修改?
代码如下
服务端

//server
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <dirent.h>
#include<fcntl.h>
#define BUFFER_SIZE 1024
void list_dir(int sockfd)
 {
    char buffer[BUFFER_SIZE];
    memset(buffer, 0, sizeof(buffer));
    DIR *dir;
    struct dirent *entry;
    if ((dir = opendir(".")) == NULL)
        {
        sprintf(buffer, "无法打开目录\n");
        if (send(sockfd, buffer, strlen(buffer), 0) < 0) {
            perror("send error");
            exit(EXIT_FAILURE);
               }
        return;
        }
while ((entry = readdir(dir)) != NULL)
 {
      if (entry->d_name[0] != '.')
           {
            strcat(buffer, entry->d_name);
            strcat(buffer, "\n");
           }
    }
    if (send(sockfd, buffer, strlen(buffer), 0) < 0)
 {
        perror("send error");
        exit(EXIT_FAILURE);
    }
}

int main(int argc, char *argv[]) 
{
    char str[100];
    char *pos;
    ssize_t n;
    FILE *fp;
    char buffer[BUFFER_SIZE];
    // 创建socket
    int listenfd = socket(AF_INET, SOCK_STREAM, 0);
    if (listenfd < 0) 
    {
        perror("socket error");
        exit(EXIT_FAILURE);
    }    
    // 设置服务端地址
    struct sockaddr_in servaddr;
    memset(&servaddr, 0, sizeof(servaddr)); //结构体初始化
    servaddr.sin_family = AF_INET;
    // servaddr.sin_port = htons(argv[2]);
    servaddr.sin_port = htons(atoi(argv[1]));
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    // 绑定端口
    if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) 
    {
        perror("bind error");
        exit(EXIT_FAILURE);
    }
    // 监听端口
    if (listen(listenfd, 5) < 0) 
    {
        perror("listen error");
        exit(EXIT_FAILURE);    
    }
    printf("服务端已启动,等待客户端连接...\n");
    // 循环接收客户端连接
    int connfd;
    struct sockaddr_in cliaddr;
    memset(&cliaddr, 0, sizeof(cliaddr));
    socklen_t clilen = sizeof(cliaddr);

        connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);
        if (connfd < 0) 
        {
            perror("accept error");
        }
        printf("客户端 %s:%d 已连接\n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));//ip地址和端口号?
        // 发送欢迎信息
        memset(buffer, 0, sizeof(buffer));
        sprintf(buffer, "欢迎连接到服务端!");
        if (send(connfd, buffer, strlen(buffer), 0) < 0) 
        {
            perror("send error");
            exit(EXIT_FAILURE);
        }
        // 循环接收命令并执行
        while (1) 
        {
             n = read(connfd, buffer, sizeof(buffer));
            //memset(buffer, 0, sizeof(buffer));
            if (n < 0)
            {
                perror("recv error");
                exit(1);
            }
            if (strcmp(buffer, "exit") == 0) 
            {
                printf("客户端 %s:%d 已断开连接\n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));
                break;
             } else if (strcmp(buffer, "ls") == 0) 
            {
                list_dir(connfd);
             } else if(strncmp(buffer,"download ",9)==0)
                {  
                char *filename = buffer + 9;
                filename[strlen(filename)-1]='\0';
                 //recv(connfd,str,1024,MSG_DONTWAIT);
                  //pos = strchr(str, ' ');
                // 打开文件
                fp = fopen(filename, "rb");
                if (fp == NULL)
                {
                                   // 文件不存在
                   strcpy(buffer, "File not found!\n");
                   write(connfd, buffer, strlen(buffer));
                } else
                                {
                    // 读取文件并发送给客户端
                    while ((n = fread(buffer, 1, 1024, fp)) > 0)
                    {
                        write(connfd, buffer, n);
                    }
                    fclose(fp);
                }
              } else {
                                // 不支持的命令
                strcpy(buffer, "Unsupported command!\n");
                write(connfd, buffer, strlen(buffer));
            }
        // 关闭客户端连接
        close(connfd);
    }
// 关闭socket
    close(listenfd);
    return 0;
}

客户端

//client
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define BUFFER_SIZE 1024
int main(int argc, char *argv[]) {  
ssize_t n;  
  // 创建socket    
 int sockfd = socket(AF_INET, SOCK_STREAM, 0);
 if (sockfd < 0) {        perror("socket error");        exit(EXIT_FAILURE);    }    
  // 设置服务端地址    
 struct sockaddr_in servaddr;    
 memset(&servaddr, 0, sizeof(servaddr));    
 servaddr.sin_family = AF_INET;    
 servaddr.sin_port = htons(atoi(argv[1]));    
 servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");    
  // 连接服务端    
 if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)  
  {        
  perror("connect error");         
  exit(EXIT_FAILURE);    
  }    
  // 接收服务端欢迎信息    
 char buffer[BUFFER_SIZE];     
 memset(buffer, 0, sizeof(buffer));    
 if (recv(sockfd, buffer, sizeof(buffer), 0) < 0)  
  {        
  perror("recv error");        
  exit(EXIT_FAILURE);    
 }    
 printf("%s\n", buffer);    
  // 循环输入命令并接收回复    
 while (1)  
 {        
      // 获取用户输入的命令
   printf("请输入命令:");         
   memset(buffer, 0, sizeof(buffer));        
   fgets(buffer, sizeof(buffer), stdin);        
   buffer[strlen(buffer) - 1] = '\0'; 

    // 发送命令到服务器
    write(sockfd, buffer, strlen(buffer));

// 读取服务器的响应
    while ((n = read(sockfd, buffer, 1024)) > 0)
    {
        fwrite(buffer, 1, n, stdout);
    } 
   //printf("%s\n", buffer);
 }    
  // 关闭socket    
 close(sockfd);    
 return 0;
}

  • 写回答

5条回答 默认 最新

  • 关注

    修改了一下server的代码,关键点就一句,在接收到数据后,如果n >0,加一句buffer[n]=0;
    代码中加了一些打印,微调了一下代码结构,if(n>0)的代码放在前面了。clent没改。
    另外一个问题是,你的服务端在n<0的时候就结束了,这么做是不对的,建议在输入exit的时候(或者连接断开的时候)退出,否则你的代码无法处理多条指令。
    运行结果:

    img

    server代码:

    //server
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <dirent.h>
    #include<fcntl.h>
    #define BUFFER_SIZE 1024
    void list_dir(int sockfd)
    {
        char buffer[BUFFER_SIZE];
        memset(buffer, 0, sizeof(buffer));
        DIR *dir;
        struct dirent *entry;
        if ((dir = opendir(".")) == NULL)
        {
            sprintf(buffer, "无法打开目录\n");
            if (send(sockfd, buffer, strlen(buffer), 0) < 0) {
                perror("send error");
                exit(EXIT_FAILURE);
            }
            return;
        }
        while ((entry = readdir(dir)) != NULL)
        {
            if (entry->d_name[0] != '.')
            {
                strcat(buffer, entry->d_name);
                strcat(buffer, "\n");
            }
        }
        if (send(sockfd, buffer, strlen(buffer), 0) < 0)
        {
            perror("send error");
            exit(EXIT_FAILURE);
        }
    }
    
    int main(int argc, char *argv[])
    {
        char str[100];
        char *pos;
        ssize_t n;
        FILE *fp;
        char buffer[BUFFER_SIZE];
        // 创建socket
        int listenfd = socket(AF_INET, SOCK_STREAM, 0);
        if (listenfd < 0)
        {
            perror("socket error");
            exit(EXIT_FAILURE);
        }
        // 设置服务端地址
        struct sockaddr_in servaddr;
        memset(&servaddr, 0, sizeof(servaddr)); //结构体初始化
        servaddr.sin_family = AF_INET;
        // servaddr.sin_port = htons(argv[2]);
        servaddr.sin_port = htons(atoi(argv[1]));
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        // 绑定端口
        if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
        {
            perror("bind error");
            exit(EXIT_FAILURE);
        }
        // 监听端口
        if (listen(listenfd, 5) < 0)
        {
            perror("listen error");
            exit(EXIT_FAILURE);
        }
        printf("服务端已启动,等待客户端连接...\n");
        // 循环接收客户端连接
        int connfd;
        struct sockaddr_in cliaddr;
        memset(&cliaddr, 0, sizeof(cliaddr));
        socklen_t clilen = sizeof(cliaddr);
    
        connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);
        if (connfd < 0)
        {
            perror("accept error");
        }
        printf("客户端 %s:%d 已连接\n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));//ip地址和端口号?
        // 发送欢迎信息
        memset(buffer, 0, sizeof(buffer));
        sprintf(buffer, "欢迎连接到服务端!");
        if (send(connfd, buffer, strlen(buffer), 0) < 0)
        {
            perror("send error");
            exit(EXIT_FAILURE);
        }
        // 循环接收命令并执行
        while (1)
        {
            n = read(connfd, buffer, sizeof(buffer));
            //memset(buffer, 0, sizeof(buffer));
            printf("receved[%d bytes]:%s\n",n,buffer);
            if(n > 0)
            {
                printf("deal %s...\n",buffer);
                buffer[n]='\0'; //mod
                if (strcmp(buffer, "exit") == 0)
                {
                    printf("客户端 %s:%d 已断开连接\n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));
                    break;
                } else if (strcmp(buffer, "ls") == 0)
                {
                    list_dir(connfd);
                } else if(strncmp(buffer,"download ",9)==0)
                {
                    char *filename = buffer + 9;
                    filename[strlen(filename)-1]='\0';
                    //recv(connfd,str,1024,MSG_DONTWAIT);
                    //pos = strchr(str, ' ');
                    // 打开文件
                    fp = fopen(filename, "rb");
                    if (fp == NULL)
                    {
                        // 文件不存在
                        strcpy(buffer, "File not found!\n");
                        write(connfd, buffer, strlen(buffer));
                    } else
                    {
                        // 读取文件并发送给客户端
                        while ((n = fread(buffer, 1, 1024, fp)) > 0)
                        {
                            write(connfd, buffer, n);
                        }
                        fclose(fp);
                    }
                } else {
                    // 不支持的命令
                    strcpy(buffer, "Unsupported command!\n");
                    write(connfd, buffer, strlen(buffer));
                }
            }
            else
            {
                perror("recv error");
                exit(1);
            }
    
            // 关闭客户端连接
            close(connfd);
        }
        // 关闭socket
        close(listenfd);
        return 0;
    }
    
    
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(4条)

报告相同问题?

问题事件

  • 系统已结题 6月19日
  • 已采纳回答 6月11日
  • 创建了问题 6月8日