TCP文件传输软件(半成品)

声明:
这篇文章是作为我记录代码之用,记录的代码是一个半成品,只能用作微小文件的传输。我将代码放在这里,一是为分享,二是为保留到之后有时间的时候去完善它,加深我对文件传输的理解。

对解决方法的思考(未实践):
用当前代码传输大文件时,接收方得到了一个同名文件,但大小比源文件小,且内容有乱码。因此推断,传输时,缓冲区可能出现了溢出,于是丢失了部分数据。最终导致接收到的文件的实际容量比源文件小。根据这一观点,我设想:在传输时,将一个大文件,以1024字节为单位拆分,传输前告知接收端要传送的文件的大小,每次只传输1024个字节,并且为每个1024字节的数据包设定一个包序号,发送端得到第n个包的收到回复再发第n+1个包,若为收到,则持续等待。若长时间未收到接受者的收到回复,则重发第n个包。发送端发送结束后,给接受者发送一个信号,提醒客户端“我这边已经发完了!”,接受者接到后,则停止接收数据,并对比收到的文件大小是否正确,正确则传输结束,不符,则删除本地文件(测试时先不做此操作,以便分析问题),然后输出错误提示。

一、服务端部分
服务端的代码分为三个部分:线程池代码——pthread_pool.c,服务端代码——my_server.c和my_server.h,把前面两部分综合起来的代码——main_server.c

main_server.c:
#include "my_server.h"

pthread_rwlock_t rwlock;//读写锁

int main()
{
    //初始化

    if(0 != pthread_rwlock_init(&rwlock,NULL))
    {
        perror("rwlock init failed ...");
        return -1;
    }
    


    P_PPSI p_ppsi = Pthread_Pool_Init();

    if(0 != sock_init(&p_ppsi->cmd_sock_fd) )
    {
        perror("sock init failed...");
        return -1;
    }

    //循环创建连接服务线程

    Enter_Add_Pthread_Task(p_ppsi);

    close(p_ppsi->cmd_sock_fd);
    
    Pthread_Pool_Free(p_ppsi);

    return 0;
}
my_server.h:
#include "my_server.h"

extern pthread_rwlock_t rwlock;//读写锁

int show_list(int stdout_fd ,char *sys_cmd, char * stdout_filename, int client_fd, char * pathname)
{
    char stdout_buf[1024] = "\0";//标准输出缓冲

    //执行查询当前路径的简洁列表,并将输出结果定向到文件中
    memset(sys_cmd,0,100);
    sprintf(sys_cmd, "ls %s >%s 2>&1",pathname,stdout_filename);
    // printf("%s\n",pathname);
    // printf("stdout_filename:%s\n",stdout_filename);
    system(sys_cmd);

    //将输出结果发送到客户端
    lseek(stdout_fd, 0, SEEK_SET);
    read(stdout_fd, stdout_buf, sizeof(stdout_buf));
    write(client_fd, stdout_buf, strlen(stdout_buf));

    return 0;
}

int change_dir(char * buf, char * pathname,int client_fd)
{
    memset(pathname, 0, sizeof(pathname));
    strcpy(pathname, buf+3);
    write(client_fd,pathname,strlen(pathname));
}

//提供下载服务时,需要上锁保护读写操作
/*
接到下载命令后,先查询该文件是否存在
若不存在,则发送“file_not_exist”,并结束当前函数
若存在,则上读锁,并发送TX_ready信号,准备发送文件

准备发送文件时,接收到客户端发送RX_ready信号,则开始循环发送数据,收到RX_cancel信号,则取消发送,结束任务
文件发送结束后则发送TX_end信号

发送出错,则发送send_err信号
*/
int download(char *sys_cmd, char * buf, char * pathname,int client_fd, int stdout_fd,char* stdout_filename)
{
    //检查文件是否存在
    // lseek(client_fd,8,SEEK_SET);
    // read(client_fd,buf,100);
    char tmp[100] = "\0";
    snprintf(sys_cmd,256,"find %s -type f -name \"%s\" > %s 2>&1",pathname, buf+9, stdout_filename);

    system(sys_cmd);
    lseek(stdout_fd,0,SEEK_SET);
    int ret = read(stdout_fd,tmp,100);
    printf("ret = %d tmp:%s\n",ret,tmp);
    if( ret == 0 || strstr(tmp,"No such file or directory") != NULL || strstr(tmp,"没有那个文件或目录") != NULL)
    {
        //文件不存在
        write(client_fd,"file_err",strlen("file_err"));
        return -1;
    }
    else
    {
        //文件存在
        if(0 == pthread_rwlock_rdlock(&rwlock))                                                                                                                                                                                                                                                                                                                                                                                                        
        {
            int src_fd = open(buf+9,O_RDWR);
            printf("%s\n",buf+9);
            if(src_fd <0)
            {
                perror("打开目标文件失败!");
                write(client_fd,"file_err",strlen("file_err"));
                return -1;
            }
            int snd_size = write(client_fd,"TX_ready",strlen("TX_ready"));
            printf("snd size = %d\n",snd_size);
            //usleep(1000);
            //发送文件
            
            // while(1);

            memset(tmp,0,sizeof(tmp));
            read(client_fd,tmp,100);
            printf("客户端:%s\n",tmp);
            //客户端取消接收准备
            if(tmp == "RX_cancel")
            {
                close(src_fd);
                pthread_rwlock_unlock(&rwlock);
                printf("客户端取消接收\n");
                return -1;
            }

            //发送数据
            // int ret = 0;
            while(1)
            {
                memset(buf,0,100);
                ret = read(src_fd,buf,100);
                // printf("%s\n",buf);
                if( ret > 0)
                {
                    write(client_fd,buf,100);
                    usleep(1000);
                }
                else if(ret == 0)
                {
                    //发送结束
                    printf("文件发送完毕!\n");
                    printf("pathname:%s\n",pathname);

                    memset(buf,0,100);
                    strcpy(buf,"TX_end");
                    write(client_fd,buf,sizeof(buf));
                    sleep(1);
                   
                    close(src_fd);
                    pthread_rwlock_unlock(&rwlock);

                    return 0;
                }
                else
                {
                    // perror("发送出错!");
                    printf("发送出错!\n");
                    close(src_fd);
                    pthread_rwlock_unlock(&rwlock);
                    return -1;
                }

            }
            
        }
    }
}

//提供上传服务时,需要上锁保护读写操作
/*
接到上传命令后,先查询该文件是否存在
若不存在,则上写锁创建文件并发送“RX_ready”信号,等待到“TX_ready”信号,开始循环读取写入
若存在,发送“file_aready_exist”信号,结束任务

准备接收文件时,若收到TX_cancel信号,则取消接收,结束任务
接收数据时,若收到“TX_end”信号,则接收结束,解写锁,任务结束

接收出错,则发送rcv_err信号,删除接收文件,结束任务
*/
int upload(char *sys_cmd, char * buf, char * pathname,int client_fd, int stdout_fd,char* stdout_filename)
{
    //准备工作
    char tmp_buf[1024] = "\0";
    char obj_pathname[100] = "\0";
    sprintf(obj_pathname,"%s/%s",pathname,buf+7);
    //查询本地是否存在同名文件
    sprintf(sys_cmd, "> %s", stdout_filename);
    system(sys_cmd);
    memset(sys_cmd,0,100);

    sprintf(sys_cmd,"find %s>%s 2>&1",obj_pathname,stdout_filename);
    printf("文件查询命令:%s\n",sys_cmd);
    system(sys_cmd);
    usleep(200);
    memset(sys_cmd,0,100);
    lseek(stdout_fd,0,SEEK_SET);
    int ret = read(stdout_fd,tmp_buf,sizeof(tmp_buf));
    printf("查询结果:ret = %d tmp_buf = %s\n",ret,tmp_buf);

    if((strstr(tmp_buf,"没有那个文件或目录") != NULL) || (strstr(tmp_buf,"No such file or directory") != NULL))
    {
        //不存在同名文件,创建文件,上写锁,发送RX_ready,准备接收文件
        if(0 > pthread_rwlock_trywrlock(&rwlock))
        {
            write(client_fd,"file_err",strlen("file_err"));
        }
        printf("111\n");
        int obj_fd = open(obj_pathname,O_RDWR|O_CREAT,777);
        if(obj_fd <0)
        {
            perror("目标文件创建失败!");
            write(client_fd,"file_err",strlen("file_err"));
            pthread_rwlock_unlock(&rwlock);
            return -1;
        }

        //准备接收
        write(client_fd,"RX_ready",strlen("RX_ready"));
        memset(tmp_buf,0, sizeof(tmp_buf));
        ret = read(client_fd,tmp_buf,sizeof(tmp_buf));
        printf("RX_ready的返回信息:ret = %d tmp_buf = %s\n",ret, tmp_buf);
        if(strcmp(tmp_buf,"TX_ready") == 0)
        {
            //开始接收数据
            while(1)
            {
                memset(tmp_buf,0, sizeof(tmp_buf));
                ret = read(client_fd,tmp_buf,sizeof(tmp_buf));
                // printf("返回信息:ret = %d tmp_buf = %s\n",ret, tmp_buf);
                //发方出错
                if(strcmp(tmp_buf,"send_err") == 0)
                {
                    //关闭并删除目标文件
                    close(obj_fd);
                    sprintf(tmp_buf,"rm %s", obj_pathname);
                    system(tmp_buf);

                    pthread_rwlock_unlock(&rwlock);

                    return 0;
                }else if(strcmp(tmp_buf,"TX_end") == 0)
                {
                    //接收成功
                    close(obj_fd);
                    printf("接收成功!\n");

                    pthread_rwlock_unlock(&rwlock);

                    return 0;
                }
                else
                {
                    //读取并写入本地
                    write(obj_fd,tmp_buf,strlen(tmp_buf));
                }
            }
            
        }
        else if(strcmp(tmp_buf,"TX_cancel") == 0)
        {
            //取消传输
            printf("客户端取消发送!\n");

            pthread_rwlock_unlock(&rwlock);

            return 0;
        }
        printf("%s\n",tmp_buf);
        close(obj_fd);
        
        pthread_rwlock_unlock(&rwlock);
        
        return 0;


    }
    else
    {
        write(client_fd,"file_err",strlen("file_err"));
        printf("111\n");
        return 0;
        //存在同名文件,发送“file_aready_exist”,任务结束

    }
}

int getinfo(char *sys_cmd, char * buf, char * pathname,int client_fd, int stdout_fd,char* stdout_filename)
{
    char stdout_buf[128] = "\0";//标准输出缓冲

    sprintf(sys_cmd, "ls %s/%s -l>%s 2>&1",pathname,buf+8,stdout_filename);
    system(sys_cmd);
    // while(1);
    // usleep(500);
    lseek(stdout_fd, 0, SEEK_SET);
    if(0 >= read(stdout_fd, stdout_buf, sizeof(stdout_buf)))
    {
        printf("读取失败!\n");
        while(1);
    }
    printf("stdout_buf:%s\n",stdout_buf);
    
    write(client_fd, stdout_buf, strlen(stdout_buf));
    printf("1\n");

    return 0;
}
int show_path(int stdout_fd ,int client_fd,char * pathname)
{
    char buf[100];
    sprintf(buf,"%s\n",pathname);
    write(client_fd,buf,strlen(buf));
    // char stdout_buf[1024] = "\0";//标准输出缓冲

    // write(stdout_fd,pathname,strlen(pathname));
    // lseek(stdout_fd, 0, SEEK_SET);
    // read(stdout_fd, stdout_buf, 1024);
    
    // write(client_fd, stdout_buf, strlen(stdout_buf));

    return 0;
}


int exct_client_cmd(int stdout_fd ,char *sys_cmd, char * buf,int buf_len, char * stdout_filename, int client_fd,char * pathname)
{
    char tmp[100] = "\0";

    if(0 == strncmp(buf, "ls", 2))
    {
        show_list(stdout_fd ,sys_cmd, stdout_filename, client_fd, pathname);
    }
    else if(0 == strncmp(buf, "cd", 2))
    {
        //查询路径是否存在
        sprintf(tmp,"find %s -type d >%s 2>&1",pathname,stdout_filename);
        system(tmp);
        read(stdout_fd,tmp,100);
        if(strstr(tmp,"没有那个文件或目录")||strstr(tmp,"No such file or directory"))
        {
            write(client_fd, "目录不存在",strlen("目录不存在"));
            return -1;
        }
        //更改路径
        change_dir(buf, pathname, client_fd);
    }
    else if(0 == strncmp(buf, "download", 8))
    {
        download(sys_cmd,  buf, pathname, client_fd,  stdout_fd, stdout_filename);
    }
    else if(0 == strncmp(buf, "upload", 6))
    {
        upload(sys_cmd,  buf,  pathname, client_fd,  stdout_fd, stdout_filename);
    }
    else if(0 == strncmp(buf, "getinfo", 7))
    {
        getinfo(sys_cmd,buf, pathname, client_fd, stdout_fd, stdout_filename);
    }
    else if(0 == strncmp(buf, "pwd", 3))
    {
        printf("execute pwd\n");
        show_path(stdout_fd, client_fd, pathname);
    }
    // else if(0 == strncmp(buf, "quit", 4))
    // {
    //     printf("服务退出 \n");
    //     return 0;
    // }
    // memset(sys_cmd, 0, sizeof(sys_cmd));
    // sprintf(sys_cmd, "%s >%s", buf, stdout_filename);//将命令输出结果重定向到指定文件中
    // system(sys_cmd);//将客户端发过来的路径、目录相关命令直接执行

    // //如果命令为pwd,则记录新路径
    // if(0 == strncmp(sys_cmd, "pwd",3))
    // {
    //     lseek(cmd_sock_fd, 0, SEEK_SET);
    //     read(stdout_fd, pathname, 100);
    //     printf("路径更新:%s\n",pathname);
    // }
    return 0;
}
/*服务线程回调函数
* 根据客户端命令提供相应服务
*
*
*/
void * server_fun(void *arg)
{
    // pthread_attr_setdetachstate(pthread_self(), NULL);
    int client_fd = (int)arg;
    printf("新客户端连接号:%d\n",client_fd);
    char sys_cmd[256] = "\0";//系统命令字符串
    char stdout_filename[100] = "\0";//标准输出定向文件名
    char buf[1024] = "\0";
    
    sprintf(stdout_filename, "stdout%d.txt", client_fd);
    int stdout_fd = open(stdout_filename,O_RDWR, O_CREAT | 777);

    //初始化路径记录
    char pathname[256] = "\0";
    sprintf(sys_cmd, "> %s", stdout_filename);
    system(sys_cmd);
    memset(sys_cmd,0,sizeof(sys_cmd));
    sprintf(sys_cmd, "pwd> %s", stdout_filename);
    system(sys_cmd);
    memset(sys_cmd,0,sizeof(sys_cmd));
    read(stdout_fd,pathname,sizeof(pathname));
    strcpy(strstr(pathname,"\n"), "\0");
    // printf("pathname:%s\n",pathname);
    // printf("断点!\n");
    //运行主体
    while(1)
    {
        memset(buf, 0, 1024);
        if(read(client_fd, buf, 1024) > 0)
        {
        printf("%d号客户端发来命令:%s\n",client_fd,buf);
        }

        //清空定向输出文件的内容
        memset(sys_cmd,0,sizeof(sys_cmd));
        sprintf(sys_cmd, "> %s", stdout_filename);
        // printf("sys_cmd:%s stdout_filename:%s\n",sys_cmd,stdout_filename);
        system(sys_cmd);
        memset(sys_cmd,0,100);

        //当前路径输出到文件
        // sprintf(sys_cmd, "pwd > %s", stdout_filename);
        // system(sys_cmd);

        if(strncmp(buf,"quit",4) == 0)
        {
            printf("服务退出!\n");
            close(client_fd);
            return 0;
        }
        //执行客户端发来的命令
        exct_client_cmd(stdout_fd ,sys_cmd, buf,1024, stdout_filename, client_fd,pathname);
        
        //设置文件描述符标志位,使其读写不阻塞
        // int flags = fcntl(stdout_fd, F_GETFL, 0); //通过设置文件描述符的属性,来设置read函数非阻塞
        // if (flags < 0)
        // {
        //     perror("获取文件描述符标志位失败");
        // }
        // fcntl(stdout_fd, F_SETFL, flags | O_NONBLOCK);
        //读取输出流,发送给客户端
        
        

        usleep(1000);
    }

}

int sock_init(int *cmd_socket_fd)
{
    struct sockaddr_in netinfo;//ipv4网络信息结构体

    //1、申请套接字
    *cmd_socket_fd = socket(AF_INET, SOCK_STREAM, 0);
    // *data_socket_fd = socket(AF_INET, SOCK_STREAM, 0); 
    
    if(*cmd_socket_fd == -1 )
    {
        perror("socket failed...");
        return -1;
    }


    printf("网络套接字申请成功cmd_socket_fd:[%d]\n",*cmd_socket_fd);

    //2、绑定套接字
    netinfo.sin_family = AF_INET;
    netinfo.sin_port = htons(56666);
    netinfo.sin_addr.s_addr = htonl(INADDR_ANY);
    if( -1 == bind(*cmd_socket_fd, ( struct sockaddr * )&netinfo, sizeof(netinfo)))//cmd
    {
        perror("bind failed...");
        return -2;
    }

    printf("绑定套接字成功!\n");

    //3、监听套接字
    listen(*cmd_socket_fd,5);


    return 0;
}


my_server.h:
#ifndef _MY_SERVER_H_
#define _MY_SERVER_H_

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netinet/in.h>
#include <pthread.h>
#include <fcntl.h>

#define PTHREAD_MAX_NUM 3000
#define EXIT_MARK 'Q'
//命令套接字
// int cmd_sock_fd;
//  pthread_rwlock_t rwlock;//读写锁

/***************线程池相关******************/

//结构体类型声明
//线程任务链表结构体类型
typedef struct task_link_node
{
    void * (*Pthread_Task)(void *arg);
    int client_fd;

    struct task_link_node * prev;
    struct task_link_node * next;
}TASK_NODE, * TASK_LINK;

//线程池状态信息结构体
typedef struct pthread_pool_inf
{
    pthread_t TID[PTHREAD_MAX_NUM];

    pthread_mutex_t mut;//互斥锁变量
    pthread_cond_t con;//条件变量

    pthread_t real_time_show_id;//实时监控线程池中线程的状态的线程的id

    TASK_LINK task_link_head;//任务链表头结点

    int task_num;//当前所剩任务数
    int pthread_sum;//线程总数
    int pthread_running_num;//活跃状态线程总数
    int pthread_sleeping_num;//睡眠状态线程总数
    int pthread_working_num;//执行任务的线程总数

    int cmd_sock_fd;//监听套接字

    int exit_mark;
}PPSI,*P_PPSI;

P_PPSI      Pthread_Pool_Init();//线程池初始化
int         Pthread_Pool_Free(P_PPSI p_ppsi);//释放线程池资源
void *      Pthread_Ctrl(void * arg);//线程控制
TASK_LINK   Create_Task_Node();//
TASK_LINK   Get_Task_Node(P_PPSI p_ppsi);
int         Add_Task_Node(TASK_LINK task_list_head, TASK_LINK new_task_node);
int         Destory_Task_List(P_PPSI p_ppsi);
int         Enter_Add_Pthread_Task(P_PPSI p_ppsi);
void *      Real_Time_Show(void * arg);
void *      Pthread_Task(void * arg);


/**********************服务功能相关程序************************/

//显示文件列表
int show_list(int stdout_fd ,char *sys_cmd, char * stdout_filename, int client_fd, char * pathname);
//更改访问目录
int change_dir(char * buf, char * pathname,int client_fd);
//提供下载服务时,需要上锁保护读写操作
/*
接到下载命令后,先查询该文件是否存在
若不存在,则发送“file_not_exist”,并结束当前函数
若存在,则上读锁,并发送TX_ready信号,准备发送文件

准备发送文件时,接收到客户端发送RX_ready信号,则开始循环发送数据,收到RX_cancel信号,则取消发送,结束任务
文件发送结束后则发送TX_end信号

发送出错,则发送send_err信号
*/
int download(char *sys_cmd, char * buf, char * pathname,int client_fd, int stdout_fd,char* stdout_filename);
//提供上传服务时,需要上锁保护读写操作
/*
接到上传命令后,先查询该文件是否存在
若不存在,则上写锁创建文件并发送“RX_ready”信号,等待到“TX_ready”信号,开始循环读取写入
若存在,发送“file_aready_exist”信号,结束任务

准备接收文件时,若收到TX_cancel信号,则取消接收,结束任务
接收数据时,若收到“TX_end”信号,则接收结束,解写锁,任务结束

接收出错,则发送rcv_err信号,删除接收文件,结束任务
*/
int upload(char *sys_cmd, char * buf, char * pathname,int client_fd, int stdout_fd,char* stdout_filename);
//获取文件详细
int getinfo(char *sys_cmd, char * buf, char * pathname,int client_fd, int stdout_fd,char* stdout_filename);
//展示当前访问路径
int show_path(int stdout_fd ,int client_fd,char * pathname);
//执行客户端指令
int exct_client_cmd(int stdout_fd ,char *sys_cmd, char * buf,int buf_len, char * stdout_filename, int client_fd,char * pathname);
//服务程序
void * server_fun(void *arg);
//套接字初始化
int sock_init(int *cmd_socket_fd);
#endif
pthread_pool.c:
#include "my_server.h"

P_PPSI Pthread_Pool_Init()
{
    //临时扩大栈空间
    // system("ulimit -s 204800");
    P_PPSI p_ppsi = (P_PPSI)malloc(sizeof(PPSI));

    if (p_ppsi == (P_PPSI)NULL)
    {
        perror("初始化失败!");
        return (P_PPSI)-1;
    }

    memset(p_ppsi, 0, sizeof(PPSI));

    if (pthread_mutex_init(&p_ppsi->mut, NULL) != 0)
    {
        perror("pthread_mutex_init...");
        return (P_PPSI)-1;
    }

    if (pthread_cond_init(&p_ppsi->con, NULL) != 0)
    {
        perror("pthread_cond_init...");
        return (P_PPSI)-1;
    }



    //创建链表头
    p_ppsi->task_link_head = Create_Task_Node();
    if(p_ppsi->task_link_head == (TASK_LINK)-1)
    {
        printf("创建任务链表头结点失败!\n");
        return (P_PPSI)-1;
    }

    p_ppsi->pthread_running_num     = 0;
    p_ppsi->pthread_sleeping_num    = 0;
    p_ppsi->pthread_working_num     = 0;
    p_ppsi->task_num                = 0;
    p_ppsi->pthread_sum             = 0;
    p_ppsi->exit_mark               = 1;

    for (int lp = 0; lp < PTHREAD_MAX_NUM; lp++)
    {
        if (pthread_create(&p_ppsi->TID[lp], NULL, Pthread_Ctrl, p_ppsi) != 0)
        {
            printf("线程数:%d\n",lp);
            perror("pthread_create...");
            return (P_PPSI)-1;
        }
        //printf("断点\n");

        //上锁
        pthread_mutex_lock(&p_ppsi->mut);
        p_ppsi->pthread_sum++;
        p_ppsi->pthread_running_num++;

        //解锁
        pthread_mutex_unlock(&p_ppsi->mut);
    }

    if(pthread_create(&p_ppsi->real_time_show_id, NULL, Real_Time_Show, p_ppsi) != 0)
    {
        perror("pthread_create...");
        return (P_PPSI)-1;
    }

    return p_ppsi;
}

TASK_LINK Create_Task_Node()
{
    TASK_LINK task_node = (TASK_LINK)malloc(sizeof(TASK_NODE));
    if(task_node == (TASK_LINK)NULL)
    {
        perror("malloc failed ...");
        return (TASK_LINK)-1;
    }

    memset(task_node, 0, sizeof(TASK_NODE));

    task_node->next = task_node;
    task_node->prev = task_node;

    return task_node;
}

void * Real_Time_Show(void * arg)
{

    P_PPSI p_ppsi = (P_PPSI)arg;
    while(p_ppsi->exit_mark)
    {
        // printf("断点!\n");

        sleep(5);
        printf("线程总数:%d ---- 任务数:%d ---- 正在执行:%d ---- 活跃:%d ---- 睡眠:%d \n",
        p_ppsi->pthread_sum,
        p_ppsi->task_num,
        p_ppsi->pthread_working_num,
        p_ppsi->pthread_running_num,
        p_ppsi->pthread_sleeping_num
        );
    }
}

void * Pthread_Ctrl(void * arg)
{
    P_PPSI p_ppsi = (P_PPSI)arg;

    while(p_ppsi->exit_mark)
    {
        //上锁
        pthread_mutex_lock(&p_ppsi->mut);

        //判断链表是否为空
        if(p_ppsi->task_num == 0)
        {
            p_ppsi->pthread_sleeping_num++;
            p_ppsi->pthread_running_num--; 
            pthread_cond_wait(&p_ppsi->con, &p_ppsi->mut);

            p_ppsi->pthread_sleeping_num--;
            p_ppsi->pthread_running_num++;
        
            pthread_mutex_unlock(&p_ppsi->mut);
        }
        else
        {
            TASK_LINK task_node = Get_Task_Node(p_ppsi);
            p_ppsi->task_num--;
            p_ppsi->pthread_working_num++;
            pthread_mutex_unlock(&p_ppsi->mut);
            
            //执行任务
            printf("执行任务\n");
            task_node->Pthread_Task(task_node->client_fd);
            printf("执行完毕\n");
            pthread_mutex_unlock(&p_ppsi->mut);
            pthread_mutex_lock(&p_ppsi->mut);//上锁
            p_ppsi->pthread_working_num--;
            free(task_node);
            printf("释放任务节点\n");
            pthread_mutex_unlock(&p_ppsi->mut);
            printf("任务完成回到等待阶段\n");

        }
    }
    pthread_exit(0);
}

TASK_LINK Get_Task_Node(P_PPSI p_ppsi)//头删获取节点
{
    TASK_LINK del_node = p_ppsi->task_link_head->next;

    del_node->next->prev = del_node->prev;
    del_node->prev->next = del_node->next;

    del_node->next = NULL;
    del_node->prev = NULL;

    return del_node;
}

//循环添加任务节点
int Enter_Add_Pthread_Task(P_PPSI p_ppsi)
{
    int client_fd = 0;
    struct sockaddr_in clientinfo;
    socklen_t addrlen = sizeof(clientinfo);
    while(1)
    {

        // char mark = getchar();

        // if(mark == EXIT_MARK)
        // {
        //     break;
        // }

        pthread_mutex_lock(&p_ppsi->mut);

        //创建新的任务节点
        TASK_LINK new_task_node = Create_Task_Node();
        if(new_task_node == (TASK_LINK)-1)
        {
            perror("创建新任务节点失败!");
            return -1; 
        }

        client_fd = accept(p_ppsi->cmd_sock_fd, (struct sockaddr * ) &clientinfo, &addrlen);
        
        if(client_fd == -1)
        {
            perror("accept failed...");
            while (1);
        }   

        printf("有新客户端连接,客户端IP:%s , 端口号: %d\n",inet_ntoa(clientinfo.sin_addr),
                                                            ntohs(clientinfo.sin_port));
        new_task_node->Pthread_Task = server_fun;
        new_task_node->client_fd = client_fd;

        Add_Task_Node(p_ppsi->task_link_head, new_task_node);

        p_ppsi->task_num++;

        pthread_mutex_unlock(&p_ppsi->mut);
        usleep(2000);

        if(pthread_cond_broadcast(&p_ppsi->con) != 0)
        {
            perror("pthread_cond_boradcast failed ...");
            return -1;
        }
        
    }

    return 0;
}

int Add_Task_Node(TASK_LINK task_link_head, TASK_LINK new_task_node)
{
    if(task_link_head == (TASK_LINK)NULL)
    {
        printf("任务头结点异常!\n");
        return -1;
    }

    new_task_node->next         = task_link_head->next;
    task_link_head->next->prev  = new_task_node;

    new_task_node->prev         = task_link_head;
    task_link_head->next        = new_task_node;

    return 0;
}

int Pthread_Pool_Free(P_PPSI p_ppsi)
{
    pthread_mutex_lock(&p_ppsi->mut);
    p_ppsi->exit_mark = 0;
    pthread_mutex_unlock(&p_ppsi->mut);

    pthread_cond_broadcast(&p_ppsi->con);

    for(int lp=0; lp<PTHREAD_MAX_NUM; lp++)
    {
        if(pthread_join(p_ppsi->TID[lp], NULL) != 0)
        {
            perror("pthread_join failed ...");
        }

        pthread_mutex_lock(&p_ppsi->mut);
        p_ppsi->pthread_sum--;
        pthread_mutex_unlock(&p_ppsi->mut);

    }

    //摧毁链表
    Destory_Task_List(p_ppsi);

    //摧毁条件变量
    pthread_mutex_destroy(&p_ppsi->mut);
    pthread_cond_destroy(&p_ppsi->con);

    pthread_join(p_ppsi->real_time_show_id, NULL);

    free(p_ppsi);
    return 0;
}

int Destory_Task_List(P_PPSI p_ppsi)
{
    if(p_ppsi->task_link_head == NULL)
    {
        printf("链表头结点异常!\n");
        return -1;
    }
    else if(p_ppsi->task_num == 0)
    {
        free(p_ppsi->task_link_head);
    }
    else
    {
        for(int lp=0; lp<p_ppsi->task_num; lp++)
        {
            TASK_LINK del_node = Get_Task_Node(p_ppsi);
            free(del_node);
            p_ppsi->task_num--;
        }

        free(p_ppsi->task_link_head);
    }

    return 0;
}

二、客户端部分
这部分,分为两部分:第一部分——main_client.c,第二部分——my_client.c和my_client.h。看名字应该能看懂各自的作用。
main_client.c:

#include "my_client.h"


int main(void)
{
    //初始化
    int cmd_sock_fd;
    // int data_sock_fd;
    char *cmd_list[] = {"ls", "download", "upload", "getinfo", "quit", "pwd"};
    char cmd_buf[1024];
    char param_buf[100];
    char data_buf[1024];
    struct sockaddr_in ser_cmd_addr;
    if(-1 == sock_init(&cmd_sock_fd))
    {
        perror("sock init failed ...");
        return -1;
    }

    //连接服务器
    ser_cmd_addr.sin_addr.s_addr = inet_addr("192.168.173.41");//inet_addr将一个表示ip地址的字符串转换成uint32_t格式
    ser_cmd_addr.sin_family = AF_INET;
    ser_cmd_addr.sin_port = htons(56666);
    if(-1 == connect(cmd_sock_fd, (struct sockaddr *)&ser_cmd_addr, sizeof(ser_cmd_addr)))
    {
        perror("connect failed...");
        return -1;
    }
    else
    {
        printf("已连接服务器!\n");
    }

    while(1)
    {
        //清屏
        system("clear");
        //打印当前路径位置
        printf("当前路径:");
        memset(cmd_buf,0,sizeof(cmd_buf));
        memset(param_buf,0,sizeof(param_buf));
        strcpy(cmd_buf, "pwd");
        exct_cmd(cmd_sock_fd,cmd_buf,param_buf);

        //打印当前文件列表
        printf("-------------------文件列表-----------------------\n");
        memset(cmd_buf,0,sizeof(cmd_buf));
        strcpy(cmd_buf,"ls");
        exct_cmd(cmd_sock_fd,cmd_buf,param_buf);

        //打印命令提示
        printf("-----------------命令提示列表-------------------\n  ls 查询当前路径文件列表\n  cd 切换路径\n  download 下载文件\n  upload 上传文件\n  getinfo 获取文件详细信息(大小、类型、日期)\n  quit 退出客户端\n");
        printf("--------------------------------------------------\n");

        //接收键盘输入的命令
        memset(cmd_buf,0,sizeof(cmd_buf));
        memset(param_buf,0,sizeof(param_buf));
        printf("请输入命令:");
        scanf("%s",cmd_buf);
        
        exct_cmd(cmd_sock_fd,cmd_buf,param_buf);
        
        sleep(1);
    }

    return 0;

}

my_client.h:

#ifndef _MY_CLIENT_H_
#define _MY_CLIENT_H_

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netinet/in.h>
#include <pthread.h>
#include <fcntl.h>

#define DEFAULT_DOWNLOAD_PATH "/download"

int sock_init(int * cmd_sock_fd);
//发送命令并显示结果
int send_cmd(int cmd_sock_fd, char *cmd_buf, char *param_buf);
//显示当前路径
int show_dir(int cmd_sock_fd,char * cmd_buf, char * param_buf);
//显示文件列表
int show_file(int cmd_sock_fd, char *cmd_buf, char *param_buf);
//切换路径
int change_dir(int cmd_sock_fd, char *cmd_buf, char *param_buf);
//下载
/*
向服务器发送download和文件名
服务端查询文件
文件存在:则收到传输开始信号——TX_ready,客户端选择路径创建文件,
建文件时若发现文件已存在则询问是否覆盖原文件,若不覆盖原文件则取消下载
创建好文件后,发送接收准备信号RX_ready,循环读取数据存放在本地文件中,当接收到TX_end
则接收结束,完成后关闭文件描述符

文件不存在:则收到错误信号file_not_exist,函数结束,返回等待命令阶段

发送出错:send_err信号
*/
int download(int cmd_sock_fd, char *cmd_buf,int cmd_buf_len , char *param_buf);
//上传
int upload(int cmd_sock_fd, char *cmd_buf,int cmd_buf_len, char *param_buf);
//获取文件信息
int getinfo(int cmd_sock_fd, char *cmd_buf, char *param_buf);
//客户端退出,发出quit信号,并释放资源
int quit(int cmd_sock_fd);
//解析并执行命令
int exct_cmd(int cmd_sock_fd, char *cmd_buf, char *param_buf);


#endif

my_client.c:

#include "my_client.h"
char server_path[100] = "\0";


int sock_init(int * cmd_sock_fd)
{
    struct sockaddr_in client_info;//ipv4网络信息结构体
    // struct sockaddr_in server_info;//ipv4服务端信息结构体

    //1、申请套接字
    *cmd_sock_fd = socket(AF_INET, SOCK_STREAM, 0);
    // *data_sock_fd = socket(AF_INET, SOCK_STREAM, 0);
    
    if(*cmd_sock_fd == -1 )
    {
        perror("socket failed...");
        return -1;
    }

    printf("网络套接字申请成功cmd_socket_fd:[%d]\n",*cmd_sock_fd);
    // printf("网络套接字申请成功cmd_socket_fd:[%d],data_socket_fd:[%d]\n",*cmd_sock_fd,*data_sock_fd);

    //2、绑定套接字 
    //cmd
    client_info.sin_family = AF_INET;
    client_info.sin_port = htons(55555);//55555用于cmd
    client_info.sin_addr.s_addr = htonl(INADDR_ANY);
    if( -1 == bind(*cmd_sock_fd, ( struct sockaddr * )&client_info, sizeof(client_info)))
    {
        perror("bind failed...");
        return -2;
    }
    //data
    // client_info.sin_port = htons(55556);//55556用于data
    // if( -1 == bind(*data_sock_fd, ( struct sockaddr * )&client_info, sizeof(client_info)))
    // {
    //     perror("bind failed...");
    //     return -2;
    // }
    printf("绑定套接字成功!\n");

    //3、监听套接字
    // listen(*data_sock_fd,5);
    // listen(*data_socket_fd,5);
    return 0;
}

//发送命令并显示结果
int send_cmd(int cmd_sock_fd, char *cmd_buf, char *param_buf)
{
    //发送命令
    // printf("已接收到的命令:%s %s\n",cmd_buf,param_buf);
    sprintf(cmd_buf,"%s %s",cmd_buf, param_buf);//拼接命令和参数
    if( -1 == write(cmd_sock_fd, cmd_buf, strlen(cmd_buf)))
    {
        perror("send cmd failed...");
    }
    usleep(50);

    //设置文件描述符标志位,使其读写不阻塞
    // int flags = fcntl(cmd_sock_fd, F_GETFL, 0); //通过设置文件描述符的属性,来设置read函数非阻塞
    // if (flags < 0)
    // {
    //     perror("获取文件描述符标志位失败");
    // }
    // fcntl(cmd_sock_fd, F_SETFL, flags | O_NONBLOCK);
    memset(cmd_buf,0,1024);
    
    read(cmd_sock_fd, cmd_buf, 1024);
    
    printf("%s",cmd_buf);
    fflush(stdout);//刷新缓冲区
    // memset(cmd_buf,0,sizeof(cmd_buf));
    // memset(param_buf,0,sizeof(param_buf));
}

//显示当前路径
int show_dir(int cmd_sock_fd,char * cmd_buf, char * param_buf)
{
    send_cmd(cmd_sock_fd,cmd_buf,param_buf);
    memset(server_path, 0, sizeof(server_path));
    strcpy(server_path, cmd_buf);
}
//显示文件列表
int show_file(int cmd_sock_fd, char *cmd_buf, char *param_buf)
{
    
    send_cmd(cmd_sock_fd,cmd_buf,param_buf);
}

//切换路径
int change_dir(int cmd_sock_fd, char *cmd_buf, char *param_buf)
{
    printf("请输入目标路径(绝对路径):\n");
    scanf("%s",param_buf);
    send_cmd(cmd_sock_fd,cmd_buf,param_buf);
    if(strstr(cmd_buf,"目录不存在") == NULL)
    {
        memset(server_path, 0, sizeof(server_path));
        strcpy(server_path, cmd_buf);
    }
    
    //切换路径后打印当前路径
    // memset(cmd_buf,0,sizeof(cmd_buf));
    // memset(param_buf,0,sizeof(param_buf));
    // strcpy(cmd_buf,"pwd");
    // send_cmd(cmd_sock_fd, cmd_buf, param_buf);
}

//下载
/*
向服务器发送download和文件名
服务端查询文件
文件存在:则收到传输开始信号——TX_ready,客户端选择路径创建文件,
建文件时若发现文件已存在则询问是否覆盖原文件,若不覆盖原文件则取消下载
创建好文件后,发送接收准备信号RX_ready,循环读取数据存放在本地文件中,当接收到TX_end
则接收结束,完成后关闭文件描述符

文件不存在:则收到错误信号file_not_exist,函数结束,返回等待命令阶段

发送出错:send_err信号
*/
int download(int cmd_sock_fd, char *cmd_buf,int cmd_buf_len , char *param_buf)
{
    //发送下载命令
    printf("请输入目标文件:");
    scanf("%s",param_buf);
    sprintf(cmd_buf,"%s %s",cmd_buf, param_buf);//拼接命令和参数
    if( -1 == write(cmd_sock_fd, cmd_buf, strlen(cmd_buf)))
    {
        perror("send cmd failed...");
    }
    usleep(50);
    //准备下载
    memset(cmd_buf,0,cmd_buf_len);
    
    int ret = read(cmd_sock_fd,cmd_buf,cmd_buf_len);
    printf("ret = %d,cmd_buf:%s\n", ret, cmd_buf);
    if(strcmp(cmd_buf , "file_err") == 0)
    {
        printf("读取文件异常,回到等待命令阶段\n");
        return -1;
    }
    else if(strcmp(cmd_buf, "TX_ready") == 0)
    {
        
        printf("服务端传输就绪!\n");
        //检查本地是否有同名文件
        int obj_fd = 0;
        char tmp_buf[1024]= "\0";
        int tmp_buf_len = 1024;
        char tmp_stdout_filename[100] =DEFAULT_DOWNLOAD_PATH;
        char tmp_download_path[100] = DEFAULT_DOWNLOAD_PATH;
        char tmp_download_filename[100] = "\0";
        umask(0000);
        
        while(1)
        {
            //是否下载在/download路径下?[y/n]
            printf("是否下载在默认路径?(默认路径:/download)[y/n]\n");
            scanf("%s",tmp_buf);
            if(strcmp(tmp_buf,"y") == 0)
            {
                //是:更改下载路径 是否使用源文件的文件名?[y/n]
                while(1)
                {
                    //是否使用源文件的文件名?[y/n]
                    memset(tmp_buf,0,sizeof(tmp_buf));
                    printf("是否使用下载文件的原文件名?[y/n]\n");
                    scanf("%s", tmp_buf);
                    if(strcmp(tmp_buf,"y") == 0)
                    {
                        //y:
                        memset(tmp_buf,0,sizeof(tmp_buf));
                        strcpy(tmp_download_filename,param_buf);
                        sprintf(tmp_buf,"%s/%s",tmp_download_path,param_buf);
                        obj_fd = open(tmp_buf,O_RDWR|O_CREAT|O_EXCL, 777);
                        

                    }
                    else if(strcmp(tmp_buf,"n") == 0)
                    {
                        //n:
                        memset(tmp_buf,0,sizeof(tmp_buf));

                        printf("自定义文件名:");
                        scanf("%s",tmp_download_filename);
                        sprintf(tmp_buf,"%s/%s",tmp_download_path,tmp_download_filename);
                        obj_fd = open(tmp_buf,O_RDWR|O_CREAT|O_EXCL, 777);
                    }
                    else
                    {
                        //错误输入
                        printf("输入错误!请重新输入!\n");
                    }

                    if (obj_fd < 0 )
                    {
                        perror("指定目录不存在,或已存在同名文件,请重新输入路径和文件名");
                        break;
                    }
                    else if(obj_fd >0)
                    {
                        break;
                    }
                }
            }
            else if(strcmp(tmp_buf, "n") == 0)
            {
                //更改下载路径
                while(1)
                {
                    memset(tmp_buf,0,sizeof(tmp_buf));
                    printf("下载路径:");
                    scanf("%s",tmp_buf);
                    strcpy(tmp_download_path,tmp_buf);

                    while(1)
                    {
                        //是否使用源文件的文件名?[y/n]
                        memset(tmp_buf,0,sizeof(tmp_buf));
                        printf("是否使用下载文件的原文件名?[y/n]\n");
                        scanf("%s", tmp_buf); 
                        if(strcmp(tmp_buf,"y") == 0)
                        {
                            //y:
                            memset(tmp_buf,0,sizeof(tmp_buf));
                            strcpy(tmp_download_filename,param_buf);
                            sprintf(tmp_buf,"%s/%s",tmp_download_path,param_buf);
                            obj_fd = open(tmp_buf,O_RDWR|O_CREAT|O_EXCL, 777);
                            

                        }
                        else if(strcmp(tmp_buf,"n") == 0)
                        {
                            //n:
                            printf("自定义文件名:");
                            scanf("%s",tmp_download_filename);
                            memset(tmp_buf,0,sizeof(tmp_buf));
                            sprintf(tmp_buf,"%s/%s",tmp_download_path,tmp_download_filename);
                            printf("pathname:%s\n",tmp_buf);
                            obj_fd = open(tmp_buf,O_RDWR|O_CREAT|O_EXCL, 777);
                        }
                        else
                        {
                            //错误输入
                            printf("输入错误!请重新输入!\n");
                        }

                        if (obj_fd < 0 )
                        {
                            perror("指定目录不存在,或已存在同名文件,请重新输入路径和文件名");
                            break;
                        }
                        else if(obj_fd >0)
                        {
                            break;
                        }
                    }

                    if(obj_fd > 0)
                    {
                        break;
                    }
                    
                }
                
            }
            else
            {
                printf("输入错误请重试!\n");
                sleep(1);
            }
            if(obj_fd > 0)
            {
                break;
            }
        }
        
        
        printf("开始接收数据。。。\n");
        //准备接收
        // obj_fd = open(param_buf,O_RDWR|O_CREAT,777);
        write(cmd_sock_fd,"RX_ready",strlen("RX_ready"));
        memset(tmp_buf,0,tmp_buf_len);
        //开始下载
        while(1)
        {
            if((read(cmd_sock_fd,tmp_buf,100) > 0) && (strcmp(tmp_buf,"TX_end") != 0) && (strcmp(tmp_buf, "send_err") != 0))
            {
                // printf("获取文件字符串:%s",tmp_buf);
                write(obj_fd,tmp_buf,strlen(tmp_buf));
                memset(tmp_buf,0,tmp_buf_len);
            }
            else if(strcmp(tmp_buf,"TX_end") == 0)
            {
                //接收over
                printf("下载完毕!\n");
                close(obj_fd);
                // sprintf(tmp_buf,"rm %s",tmp_stdout_filename);
                // system(tmp_buf);
                return 0;
            }
            else if(strcmp(tmp_buf, "send_err") == 0)
            {
                //发方出错
                close(obj_fd);
                memset(tmp_buf,0,tmp_buf_len);
                sprintf(tmp_buf,"rm %s",tmp_download_filename);
                system(tmp_buf);

                // memset(tmp_buf,0,tmp_buf_len);
                // sprintf(tmp_buf,"rm %s",tmp_stdout_filename);
                // system(tmp_buf);
                return -1;
            }
            else
            {
                //接收出错
                close(obj_fd);
                memset(tmp_buf,0,tmp_buf_len);
                sprintf(tmp_buf,"rm %s",tmp_download_filename);
                system(tmp_buf);

                // memset(tmp_buf,0,tmp_buf_len);
                // sprintf(tmp_buf,"rm %s",tmp_stdout_filename);
                // system(tmp_buf);
                return -1;
            }
        }
    }
    


    memset(cmd_buf, 0, cmd_buf_len);
    strcpy(cmd_buf, "ls");
    sprintf(param_buf, "%s/%s -l",server_path,param_buf);
    send_cmd(cmd_sock_fd,cmd_buf,param_buf);

}

//上传
int upload(int cmd_sock_fd, char *cmd_buf,int cmd_buf_len, char *param_buf)
{
    //准备工作
    char tmp_buf[100] = "\0";
    //发送上传命令
    printf("请输入要上传的文件:");
    scanf("%s",param_buf);
    sprintf(cmd_buf,"%s %s",cmd_buf, param_buf);//拼接命令和参数
    printf("上传命令:%s\n",cmd_buf);
    if( -1 == write(cmd_sock_fd, cmd_buf, strlen(cmd_buf)))
    {
        perror("send cmd failed...");
    }

    //确认是否存在同名文件
    memset(cmd_buf,0, cmd_buf_len);
    read(cmd_sock_fd,cmd_buf,cmd_buf_len);
    printf("cmd_buf :%s\n",cmd_buf);
    if(strcmp(cmd_buf, "RX_ready") == 0)
    {
        //不存在同名文件
        int src_fd = open(param_buf,O_RDONLY);
        if(src_fd < 0)
        {
            perror("源文件打开失败!取消传输!");
            write(cmd_sock_fd,"TX_cancel",strlen("TX_cancel"));
            return -1;
        }
        //发送“TX_ready”信号
        write(cmd_sock_fd,"TX_ready",strlen("TX_ready"));
        printf("服务器准备接收数据!\n");
        while (1)
        {
            //发送数据
            memset(tmp_buf,0,sizeof(tmp_buf));

            int ret = read(src_fd, tmp_buf,sizeof(tmp_buf));
            // printf("读取内容:ret = %d tmp_buf = %s\n",ret, tmp_buf);
            if(ret <0)
            {
                //传输出错
                perror("读取失败,取消传输!");
                close(src_fd);
                write(cmd_sock_fd,"send_err",strlen("send_err"));
                usleep(1000);
                return -1;
            }else if(ret == 0)
            {
                //传输完成
                printf("传输完成!发送TX_end信号!\n");
                write(cmd_sock_fd, "TX_end", strlen("TX_end"));
                close(src_fd);
                usleep(1000);
                return 0;
            }

            // printf("读取源文件:ret = %d tmp_buf = %s\n",ret , tmp_buf);
            ret = write(cmd_sock_fd,tmp_buf,100);
            // printf("写入字节数:%d 内容:%s\n",ret, tmp_buf);

            usleep(1000);
        }
        
    }
    else if(strcmp(cmd_buf, "file_err") == 0)
    {
        //存在同名文件
        printf("存在同名文件,或写入文件失败,无法上传!\n");
        return -1;

    }
   
}

//获取文件信息
int getinfo(int cmd_sock_fd, char *cmd_buf, char *param_buf)
{
    printf("请输入目标文件:");
    scanf("%s",param_buf);
    send_cmd(cmd_sock_fd,cmd_buf,param_buf);
    sleep(6);
}

//客户端退出,发出quit信号,并释放资源
int quit(int cmd_sock_fd)
{
    write(cmd_sock_fd,"quit",sizeof("quit"));
    sleep(1);
    close(cmd_sock_fd);
    exit(0);
}

//解析并执行命令
int exct_cmd(int cmd_sock_fd, char *cmd_buf, char *param_buf)
{
    if(0 == strcmp(cmd_buf, "pwd"))
    {
        // printf("%s\n",cmd_buf);
        show_dir(cmd_sock_fd,cmd_buf, param_buf);
        return 0;
    }
    else if(0 == strcmp(cmd_buf, "ls"))
    {
        show_file(cmd_sock_fd,cmd_buf, param_buf);
        return 0;
    }
    else if(0 == strcmp(cmd_buf, "cd"))
    {
        // printf("%s\n",cmd_buf);
        change_dir(cmd_sock_fd,cmd_buf, param_buf);
        return 0;
    }
    else if(0 == strcmp(cmd_buf, "download"))
    {
        download( cmd_sock_fd, cmd_buf,100, param_buf);
        return 0;
    }
    else if(0 == strcmp(cmd_buf, "upload"))
    {
        upload(cmd_sock_fd, cmd_buf,100, param_buf);
        return 0;
    }
    else if(0 == strcmp(cmd_buf, "getinfo"))
    {
        getinfo(cmd_sock_fd,cmd_buf, param_buf);
        return 0;
    }
    else if(0 == strcmp(cmd_buf, "quit"))
    {
        quit(cmd_sock_fd);
    }
    else
    {
        printf("输入命令有误!\n");
        return -1;
    }


    
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值