Linux系统下C语言实现百度网盘(附实现步骤,和全部代码讲解)

news2024/11/27 15:41:09

Linux系统下C语言实现百度网盘

  • Linux操作系统下用C语言写一个网盘
  • 完整代码:
    • 服务器
    • 客户端

Linux操作系统下用C语言写一个网盘

本次实验完成了完整的网盘功能(查询文件,下载文件,上传文件,刷新界面,和退出系统),包括附加功能查询特定目录下的文件进行下载或者上传)。

  • 初始文件分配,在根目录下的初始文件是dd.txt ee.txt 而./download里面的文件是a.txt b.txt c.txt.。 分别用于客户下载和客户上传文件。

在这里插入图片描述
在这里插入图片描述

  • 刷新网盘的界面: 当用户输入4,重新输入网盘的可视化界面,并且让用户选择执行的操作。

在这里插入图片描述

void net_disk_ui()   //网盘可视化页面
{
    printf("======================TCP网盘客户端==================\n");
    printf("=========================功能菜单====================\n");
    printf("\t\t\t1.查询文件\n");
    printf("\t\t\t2.下载文件\n");
    printf("\t\t\t3.上传文件\n");
    printf("\t\t\t4.刷新界面\n");
    printf("\t\t\t0.退出系统\n");
    printf("------------------------------------------------------\n");
    printf("请选择你要执行的操作: \n");
}
case '4':
{
    net_disk_ui();
}
  • 查询文件: 当用户输入1,输出home/drj/目录下的文件列表

在这里插入图片描述

case '1':   //  要让服务器给我们发送目录信息->客户端也要创捷线程
    // 这个while循环本身也是死循环,我们要让客户端也创建线程,让接受服务器的数据的代码放进线程中
    send_msg.type = MSG_TYPE_FILENAME;
    res = write(client_socket, &send_msg, sizeof(MSG));
    if (res < 0)
    {
        perror("send msg error: ");
    }
    memset(&send_msg, 0, sizeof(MSG));
    break;
  • 下载文件: 根据给定被下载文件的路径以及需要下载的指定位置,连续下载两个文件,并且下载路径和内容无误
    • 当用户输入2的时候,先显示当前目录/home/drj目录下有哪些内容,让用户进行选择下载哪一个文件
    • 经过下载,./download目录下由dd.txt 和 ee.txt这两个文件,并且核对文件内容无误,下载成功操作。

在这里插入图片描述

// 客户端
case '2':
{
    send_msg.type = MSG_TYPE_DONWLOAD;
    struct dirent* dir = NULL;
    printf("there are  files in /home/drj : \n");
    DIR* dp = opendir("/home/drj");
    while (1)
    {
        dir = readdir(dp);
        if (NULL == dir)
        {
            break;
        }
        if (dir->d_name[0] != '.')
            printf("%s  ", dir->d_name);
    }
    printf("\ninput download filename: \n");
    scanf("%s", down_file_name);
    strcpy(send_msg.fname, down_file_name);
    res = write(client_socket, &send_msg, sizeof(MSG));
    if (res < 0)
    {
        perror("send msg error: ");
    }
    memset(&send_msg, 0, sizeof(MSG));
    break;
}
// 服务器
else if (recv_msg.type == MSG_TYPE_DONWLOAD)
{
    strcpy(down_file_name, recv_msg.fname);
    printf("要下载的文件是%s\n", down_file_name);
    server_file_download(acpt_socket);
    memset(&recv_msg, 0, sizeof(MSG));
}
  • 上传文件: 将download下文件a.txt b.txt c.txt上入 /home/drj目录下,传递完成,服务器和客户端都没有错误,并且上传的字节数和内容无误。
    • 输入3 ,给用户展示当前文件夹先有的文件,并且让用户选择一个进行上传。给出上传文件的路径以及当前文件的大小。
    • 连续上传三个文件,然后在根目录下检查文件是否上传成功,以及文章内容是否正确等。可以看到,三个文件全部上传成功并且文件内容全部正确。

在这里插入图片描述

// 客户端
case '3': {        
    send_msg.type = MSG_TYPE_UPLOAD;
    struct dirent* dir = NULL;
    printf("there are  files in ./download  : \n");
    DIR* dp = opendir("./download");
    while (1)
    {
        dir = readdir(dp);
        if (NULL == dir)
        {
            break;
        }
        if (dir->d_name[0] != '.')
            printf("%s  ", dir->d_name);
    }
    printf("\ninput upload filename: \n");
    scanf("%s", up_file_name);
    // 发送一个数据包告诉服务器,准备上传文件了
    strcpy(send_msg.fname, up_file_name);
    // f发送数据给服务器
    res = write(client_socket, &send_msg, sizeof(MSG));
    if (res < 0)
    {
        perror("send upload packege error");
        continue; //不走下面了
    }
    memset(&send_msg, 0, sizeof(MSG));
    // 由于考虑到上传文件是需要时间的,如果文件很大,那么就需要非常长的时间
    // 如果这个时候写在这里会导致其他功能卡住,因此需要把发送文件内容的代码放进线程里面,因此需要创建线程
    // 因此我们客户都拿还需要创建一个新的线程,专门处理文件的上传任务;
    pthread_create(&pthread_send_id, NULL, upload_file_thread, &client_socket); //创建一个线程
    break;
}

// 服务器
else if (recv_msg.type == MSG_TYPE_UPLOAD)  //如果收到的是上传包,说明准备接受客户端发来的文件数据
{
    printf("进入upload\n");

    //从数据包的文件名获取文件名信息并创建文件,默认创建的文件夹在家目录下
    strcpy(up_file_name, recv_msg.fname);

    char path[20] = "/home/drj/";
    strcat(path, up_file_name);
    printf("当前要下载到的文件位置是 %s \n", path);
    // 创建文件,在家目录下,下需要定义文件名描述符
    fd = open(path, O_CREAT | O_WRONLY, 0666);
    if (fd < 0)
    {
        perror("create up file error");
    }
}
else if (recv_msg.type == MSG_TYPE_UPLOAD_DATA)
{
    // 写的字节数是recv_msg.bytes
    printf("文件开始开始上传\n");
    res = write(fd, recv_msg.buffer, recv_msg.bytes);
    
    if (recv_msg.bytes < sizeof(recv_msg.buffer))
    {
        //说明是最后一个包,这部分数据是文件的最后数据了
        printf("client up file ok\n");
        close(fd);
    }
    memset(&recv_msg, 0, sizeof(MSG));
}

完整代码:

服务器

#include <cstdio>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

char down_file_name[20] = { 0 };
#define MSG_TYPE_LOGIN 0
#define MSG_TYPE_FILENAME 1
#define MSG_TYPE_DONWLOAD 2
#define MSG_TYPE_UPLOAD 3
#define MSG_TYPE_UPLOAD_DATA 4

typedef struct msg
{
    int type; // 协议类型  0 表示登录协议,1表示文件传输包 2 表示文件下载
    int flag; 
    char buffer[1024];  //存放除文件名之外的内容
    char fname[50];  //如果type是1 就是文件名传输包,这个结构体会添加新的字段;
    int bytes;   // 这个字段用来记录传输文件时候每个数据包实际的文件数
}MSG;//这个结构体会根据业务需求的不断变化,会添加新的字段。


void search_server_dir(int accept_socket)
// 通过打开服务器中的某个文件,并使用  socket 网络发送给客户端  至于什么文件我们先顶一个。。。e
//可以根据实际情况定义
{
    struct dirent * dir = NULL;   //定义目录的结构体;
    MSG info_msg = { 0 };
    int res = 0;
    //opendir 是打开Linux目录的api函数
    DIR* dp = opendir("/home/drj");
    info_msg.type = MSG_TYPE_FILENAME;
    if (NULL == dp)
    {
        perror("open dir error: ");
        return;
    }
    while (1)
    {
        dir = readdir(dp);
        if (NULL == dir) //目录遍历完成,函数返回空值,表示目录全部读取完成
        {
            break;
        }
        if (dir->d_name[0] != '.') //过滤掉.隐藏文屏蔽 
        {
            printf("name = %s\n", dir->d_name);
            memset(info_msg.fname, 0, sizeof(info_msg.fname));
            strcpy(info_msg.fname, dir->d_name);
            res = write(accept_socket, &info_msg, sizeof(MSG)); //把每个文件名拷贝到
            // info_msg结构体中,通过该套接字发送出去。
            if (res < 0)
            {
                perror("send client error: ");
                return;
            }
        }
    }
}

void server_file_download(int accept_socket)
{
    MSG  file_msg = { 0 };
    int res = 0;
    int fd;   //文件描述符  linux系统下很重要的概念,linux认为所有设备都是文件描述符。对文件的 打开对设备。
    // 都可以使用文件描述符概念。
    char path[20] = "/home/drj/";
    strcat(path, down_file_name);
    fd = open(path, O_RDONLY);

    if (fd < 0)
    {
        perror("file open error: ");
        return;
    }
    // 在读取文件并把文件传到客户端,这个时候msg结构体中的buffer 就是存放文件的内容,
    // 但是一般来说文件都超过1024,所以要发送多个包;
    file_msg.type = MSG_TYPE_DONWLOAD;
    strcpy(file_msg.fname, "ee.txt");

    while ((res = read(fd, file_msg.buffer, sizeof(file_msg.buffer))) > 0)
        // read用于读取文件的时候,当文件读到末尾的时  
        // res是实际读到的字节
    {
        file_msg.bytes = res;
        res = write(accept_socket, &file_msg, sizeof(MSG));
        if (res <= 0)
        {
            perror("server send file error: ");
        }
        memset(file_msg.buffer, 0, sizeof(file_msg.buffer));
    }

}

void* thread_fun(void* arg)
{
    int acpt_socket = *((int*)arg);
    int res;
    char buffer[50] = { 0 };
    char up_file_name[20] = { 0 };
    MSG recv_msg = { 0 };
    int fd = -1;  //定义一个打开文件的描述符
    //read函数就是接受客户端发来的数据,返回实际从客户端那边收到的字节数。
    //buffer: 收到客户端数据后把数据存放的地址  sizeof(buffer) 就是希望读取的字节数
    //search_server_dir(acpt_socket);
    printf("目录发送客户端完成!\n");
    while (1)
    {
        // todo  #################################sizeof(recv_msg)
        res = read(acpt_socket, &recv_msg, sizeof(recv_msg));
        if (res == 0)  //说明客户端已经断开,read默认情况下他是堵塞模式,回答问题才能说出下一句话
        {
            printf("客户端已经断开");
            break;    // 线程结束
        }
        if (recv_msg.type == MSG_TYPE_FILENAME) //说明客户端发过来的是目录
        {
            search_server_dir(acpt_socket);
            memset(&recv_msg, 0, sizeof(MSG));
        }
        else if (recv_msg.type == MSG_TYPE_DONWLOAD)
        {
            strcpy(down_file_name, recv_msg.fname);
            printf("要下载的文件是%s\n", down_file_name);
            server_file_download(acpt_socket);
            memset(&recv_msg, 0, sizeof(MSG));
        }
        else if (recv_msg.type == MSG_TYPE_UPLOAD)  //如果收到的是上传包,说明准备接受客户端发来的文件数据
        {
            printf("进入upload\n");

            //从数据包的文件名获取文件名信息并创建文件,默认创建的文件夹在家目录下
            strcpy(up_file_name, recv_msg.fname);

            char path[20] = "/home/drj/";
            strcat(path, up_file_name);
            printf("当前要下载到的文件位置是 %s \n", path);
            // 创建文件,在家目录下,下需要定义文件名描述符
            fd = open(path, O_CREAT | O_WRONLY, 0666);
            if (fd < 0)
            {
                perror("create up file error");
            }
        }
        else if (recv_msg.type == MSG_TYPE_UPLOAD_DATA)
        {
            // 写的字节数是recv_msg.bytes
            printf("文件开始开始上传\n");
            res = write(fd, recv_msg.buffer, recv_msg.bytes);
            
            if (recv_msg.bytes < sizeof(recv_msg.buffer))
            {
                //说明是最后一个包,这部分数据是文件的最后数据了
                printf("client up file ok\n");
                close(fd);
            }
            memset(&recv_msg, 0, sizeof(MSG));
        }
        // printf("client read %s\n", buffer);
        // write(acpt_socket, buffer, res);
         memset(&recv_msg, 0, sizeof(MSG));
        //服务器收到客户端数据后,原封不动的发给客户端
    }
}
int main()
{
    char buffer[50] = { 0 };
    int res = 0;
    int server_socket; //这个是socket网络描述符,也叫套接字描述符。
    int accept_socket;
    // 第一步:创建套接字描述符       --“买一部手机”
    pthread_t thread_id; //线程编号

    
    printf("开始创建tcp服务器\n");
    server_socket = socket(AF_INET, SOCK_STREAM, 0);//我们想要向网络发送数据都使用
    //server_socket这个套接字描述符

    if (server_socket < 0)
    {
        perror("socket create failed:");
        return 0;
    }

    // 第二步:要告诉这个服务器 我的ip地址和端口号 我们要有一个保存ip地址和端口的变量
                //          --“买电话卡”
    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET; // 表示ipv4地址协议
    server_addr.sin_addr.s_addr = INADDR_ANY;   //inaddr_any 存服务器ip地址,告诉系统自动绑定网卡ip地址
    server_addr.sin_port = htons(1046);    //网络地址转换,把主机字节顺序转换成网络字节顺序
    // 端口号1024以上即可。
    // 
    // 
    // 如果服务器程序退出之后,又立刻打开服务器,系统会提示地址已经被使用
    //这是因为ip地址和端口号是系统资源,必须设置为端口号为重复使用。
    int optvalue = 1;
    setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &optvalue, sizeof(optvalue));
    // 第三步:把我们设定好的ip地址和端口号绑定到我们的server_socket描述符上。 --“把电话卡插入手机上”

    if (bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0)
    {
        perror("server bind error:");
        return 0;
    }

    // 第四步:我们调用listen 开始监听程序    --“把电话放在身上,电话铃响听到声音”
    if (listen(server_socket, 10) < 0)
    {
        perror("server listen error:");
        return 0;
    }

    // 第五步:以上4个步骤都ok后,我们就可以等待客户端连接过来了。

    // accept 函数有一个特点,当我们程序调用这个函数的时候,如果没有客户端连接到我们的服务器,
    // 那么这个函数将堵塞(程序停下不走了),直到有客户端连接到服务器,这个函数将解开,并
    // 并且返回一个新的套接字描述符。那么后期和客户端的通讯都交给这个新的套接字描述符来负责。
    printf("TCP服务器准备完成,等待客户端连接!\n");
    
    while (1)
    {
        accept_socket = accept(server_socket, NULL, NULL);
		printf("有客户端连接到服务器!\n");
        //创建一个新的线程,创建成功之后,系统就会执行‘thread_fun’代码,这里就是多线程代码。
        pthread_create(&thread_id, NULL, thread_fun, &accept_socket);   // 第三个参数  函数指针 真正执行函数的指针
        // 移动到最前面函数里面去了。
    }

    printf("%s 向你问好!\n", "LINUX_C_SAMPLE");
    return 0;
}

客户端

#include <cstdio>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>

// 编写客户端
#define MSG_TYPE_LOGIN 0
#define MSG_TYPE_FILENAME 1
#define MSG_TYPE_DONWLOAD 2
#define MSG_TYPE_UPLOAD 3
#define MSG_TYPE_UPLOAD_DATA 4
char down_file_name[20] = { 0 };
char up_file_name[20] = { 0 };
typedef struct msg
{
    int type; // 协议类型  0 表示登录协议,1表示文件传输包
    int flag;
    char buffer[1024]; //存放除文件名之外的内容
    char fname[50]; //如果type是1 就是文件名传输包,这个结构体会添加新的字段;
    int bytes; // 这个字段用来记录传输文件时候每个数据包实际的文件数
}MSG;//这个结构体会根据业务需求的不断变化,会添加新的字段。
  // 全局变量  用来打开文件进行读写的文件描述符,默认情况下为0
int fd = -1;//进行读写的文件标识符
void net_disk_ui()
{
    printf("======================TCP网盘客户端==================\n");
    printf("=========================功能菜单====================\n");
    printf("\t\t\t1.查询文件\n");
    printf("\t\t\t2.下载文件\n");
    printf("\t\t\t3.上传文件\n");
    printf("\t\t\t4.刷新界面\n");
    printf("\t\t\t0.退出系统\n");
    printf("------------------------------------------------------\n");
    printf("请选择你要执行的操作: \n");

}
// 根据网盘客户端业务需求,客户端想要查看下服务器这边目录下的文件信息。因此
// 服务器必须设计一个功能,把某个目录下的文件名信息全部获取出来发给客户端。
// 默认情况下服务器的目录,用户的目录设置为家home目录
// 在Linux下如何对文件和目录进行读取并获取文件名


void * thread_func(void* arg)
{
    int client_socket = *((int*)arg);
    MSG recv_msg = { 0 };
    int res;
    char pwd[100] = { 0 } ;
    while (1)
    {
        //用来接受服务器发过来的数据
        res = read(client_socket, &recv_msg, sizeof(MSG));
        if (recv_msg.type == MSG_TYPE_FILENAME)
        {
            printf("server path filename=%s\n", recv_msg.fname);
            memset(&recv_msg, 0, sizeof(MSG));
        }
        else if (recv_msg.type == MSG_TYPE_DONWLOAD)  // 做好接受准备,一定是一个文件
        {

            // 1.创建一个目录
            if (mkdir("download", S_IRWXU) <0 )
            {
                if (errno == EEXIST)
                {
                    printf("download dir exist continue!!\n");
                }
                else
                {
                    perror("mkdir error: ");
                }
            }
            // 目录创建没有问题,就要开始创建文件了。
            if (fd == -1)  //表示文件还没打开过,若非0 已经打开过了
            {
                //printf("\ncurrent = %s\n", getcwd(NULL,0));
                char path[20] = "./download/";
                strcat(path, down_file_name);
                printf("download path = %s\n", path);
                fd = open(path, O_CREAT | O_WRONLY, 0666); //打开过肯定会有个文件描述返回  0666读写可执行
                if (fd < 0)
                {
                    perror("file open error: ");
                }

            }
            // 通过上面的创建目录以及文件描述的判断,通过后就可以从MSG结构体里面的buffer取数据了。
            // recv_msg.buffer  存放的就是文件的部分内容。 recv_msg.bytes就这个部分文件的字节。
            res = write(fd, recv_msg.buffer, recv_msg.bytes);
            if (res < 0)
            {
                perror("file write error : ");
            }
            // 那么我们判断文件的内容都全部发完了吗?通过recv_msg.bytes 如果小于recv_buffer的1024 
            if (recv_msg.bytes < sizeof(recv_msg.buffer))
            {
                printf("file download finish!!\n");
                close(fd);
                fd = -1;
            }
        }

    }
}

void* upload_file_thread(void * args)
{
    // 客户端实现上传文件到服务器逻辑
    // 1.打开文件 
    MSG up_file_msg = { 0 };
    int client_socket = *((int*)args);
    int fd = -1;
    int res = 0;  //实际读入的文件名
    char buffer[1024] = { 0 }; //用来保存读取文件的缓冲区数据


    char path[20] = "./download/";
    strcat(path, up_file_name);
    printf("客户端上传文件的路径是%s \n", path);
    fd = open(path, O_RDONLY);
    if (fd < 0)
    {
        perror("client  open up file error:");
        return NULL;
    }
    up_file_msg.type = MSG_TYPE_UPLOAD_DATA;
    //2.读取文件
    while ((res = read(fd, buffer, sizeof(buffer)) )> 0)
    {
        // 要把文件数据拷贝到MSG结构体中的buffer中
        printf("传入的字节数目:%d 字节\n", res);
        memcpy(up_file_msg.buffer, buffer, res);
        up_file_msg.bytes = res;
        res = write(client_socket, &up_file_msg, sizeof(MSG));//写的字节数一定是读的总数据
        memset(buffer, 0, sizeof(buffer));
        memset(up_file_msg.buffer, 0, sizeof(up_file_msg.buffer));
    }
}


int main()
{
    int client_socket;
    //todo 定义
    pthread_t  pthread_id;  //线程编号
    pthread_t  pthread_send_id;
    char c;
    struct sockaddr_in server_addr; //用来连接到服务器的ip地址和端口号
    char buffer[50] = { 0 };
    client_socket = socket(AF_INET,SOCK_STREAM,0);
    int res;
    MSG recv_msg = { 0 };
    MSG send_msg = { 0 };
    if (client_socket < 0)
    {
        perror("client socket faile: ");
        return 0;
    }
    server_addr.sin_family = AF_INET; //ipv协议 且自动匹配绑定 
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    // 两种方法如果服务器和客户端都在同一台电脑中,ip地址可以设置为127.0.0.1
    // 现在就是服务器和客户端中在同一个机子上,因此可以127.0.0.1.
    server_addr.sin_port = htons(1046);
    printf("这是客户端\n");
    // 创建好套接字之后,客户端要连接到服务器,使用conect()函数

    if (connect(client_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0)
    {
        perror("connect error:  ");
        return 0;
    }
    printf("客户端连接服务器成功\n");
    
    pthread_create(&pthread_id, NULL, thread_func, &client_socket);
    net_disk_ui();
    // 我们用户在客户端中连续输入字符,回车表示把数据发出去,把buffer里的数据发出去;服务器有固定ip地址即可,不一定在一个主机上
    while (1)
    {
        c = getchar();
        switch (c)
        {
        case '1':   //  要让服务器给我们发送目录信息->客户端也要创捷线程
            // 这个while循环本身也是死循环,我们要让客户端也创建线程,让接受服务器的数据的代码放进线程中
            send_msg.type = MSG_TYPE_FILENAME;
            res = write(client_socket, &send_msg, sizeof(MSG));
            if (res < 0)
            {
                perror("send msg error: ");
            }
            memset(&send_msg, 0, sizeof(MSG));
            break;
        case '2':
        {
            send_msg.type = MSG_TYPE_DONWLOAD;
            struct dirent* dir = NULL;
            printf("there are  files in /home/drj : \n");
            DIR* dp = opendir("/home/drj");
            while (1)
            {
                dir = readdir(dp);
                if (NULL == dir)
                {
                    break;
                }
                if (dir->d_name[0] != '.')
                    printf("%s  ", dir->d_name);
            }
            printf("\ninput download filename: \n");
            scanf("%s", down_file_name);
            strcpy(send_msg.fname, down_file_name);
            res = write(client_socket, &send_msg, sizeof(MSG));
            if (res < 0)
            {
                perror("send msg error: ");
            }
            memset(&send_msg, 0, sizeof(MSG));
            break;
        }
        case '3': {        
            send_msg.type = MSG_TYPE_UPLOAD;
            struct dirent* dir = NULL;
            printf("there are  files in ./download  : \n");
            DIR* dp = opendir("./download");
            while (1)
            {
                dir = readdir(dp);
                if (NULL == dir)
                {
                    break;
                }
                if (dir->d_name[0] != '.')
                    printf("%s  ", dir->d_name);
            }
            printf("\ninput upload filename: \n");
            scanf("%s", up_file_name);
            // 发送一个数据包告诉服务器,准备上传文件了
            strcpy(send_msg.fname, up_file_name);
            // f发送数据给服务器
            res = write(client_socket, &send_msg, sizeof(MSG));
            if (res < 0)
            {
                perror("send upload packege error");
                continue; //不走下面了
            }
            memset(&send_msg, 0, sizeof(MSG));
            // 由于考虑到上传文件是需要时间的,如果文件很大,那么就需要非常长的时间
            // 如果这个时候写在这里会导致其他功能卡住,因此需要把发送文件内容的代码放进线程里面,因此需要创建线程
            // 因此我们客户都拿还需要创建一个新的线程,专门处理文件的上传任务;
            pthread_create(&pthread_send_id, NULL, upload_file_thread, &client_socket); //创建一个线程
            break;
        }
        case '4':
        {
            net_disk_ui();
        }
        }
    }
    /*
    while (1)
    {
 
        res = read(client_socket, &recv_msg, sizeof(MSG));


        if (recv_msg.type == MSG_TYPE_FILENAME)
        {
            printf("server path filename = %s\n", recv_msg.fname);
            memset(&recv_msg, 0, sizeof(MSG));
        }
        
    }
    */


    /*
    //用户在客户端中连续输入字符,回车发送数据
    while (fgets(buffer, sizeof(buffer), stdin) != NULL)
    {
        res = write(client_socket, buffer, sizeof(buffer));
        printf("send bytes =%d\n", res);
        memset(buffer, 0, sizeof(buffer));

        res = read(client_socket, buffer, sizeof(buffer));
        printf("recv from server info : % s\n", buffer);
        memset(buffer, 0, sizeof(buffer));
    }
    */


    printf("%s 向你问好!\n", "linux_02");
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1055961.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

服务器流量只有1tb,害怕被刷怎办,这篇文章教你防止对方刷流量!

本篇文章主要讲解&#xff0c;服务器流量监控和关闭网络请求的方法教程&#xff0c;在某种情况下可以有效杜绝被刷流量的困扰。 日期&#xff1a;2023年10月2日 作者&#xff1a;任聪聪 根本有效避免刷流的前置办法 说明&#xff1a;只选择固定带宽&#xff0c;不限流量的服务器…

【Linux进行时】进程地址空间

进程地址空间 例子引入&#xff1a; 我们在讲C语言的时候&#xff0c;老师给大家画过这样的空间布局图&#xff0c;但是我们对它不了解 我们写一个代码来验证Linux进程地址空间 #include<stdio.h> #include<assert.h> #include<unistd.h> int g_value100; …

【吞噬星空】连播两集,尼赫鲁对徐欣动手,罗峰修分身强势复仇

Hello,小伙伴们&#xff0c;我是小郑继续为大家深度解析吞噬星空资讯。 吞噬星空动画第四季定档之后&#xff0c;官方真的是太宠粉了&#xff0c;每天都会公布全新预告情报&#xff0c;无论是外星人物角色&#xff0c;亦或者宇宙星球建模&#xff0c;那都是相当的炸裂。如今更…

《CTFshow-Web入门》10. Web 91~110

Web 入门 索引web91题解总结 web92题解总结 web93题解 web94题解 web95题解 web96题解 web97题解 web98题解 web99题解总结 web100题解 web101题解 web102题解 web103题解 web104题解 web105题解总结 web106题解 web107题解 web108题解 web109题解 web110题解 ctf - web入门 索…

怒刷LeetCode的第22天(Java版)

目录 第一题 题目来源 题目内容 解决方法 方法一&#xff1a;回溯算法 方法二&#xff1a;基于位运算的回溯 第二题 题目来源 题目内容 解决方法 方法一&#xff1a;动态规划 方法二&#xff1a;分治法 方法三&#xff1a;前缀和数组 第三题 题目来源 题目内容…

通讯网关软件014——利用CommGate X2HTTP实现HTTP访问OPC Server

本文介绍利用CommGate X2HTTP实现HTTP访问OPC Server。CommGate X2HTTP是宁波科安网信开发的网关软件&#xff0c;软件可以登录到网信智汇(http://wangxinzhihui.com)下载。 【案例】如下图所示&#xff0c;SCADA系统配置OPC Server&#xff0c;现在上位机需要通过Http Client…

Springboot+Vue+Mysql实现模拟汽车保养系统(附源码)

前言 本项目基于springbootvue搭建的汽车保养的系统&#xff0c;页面较为粗糙&#xff0c;前端好的小伙伴可自行优化。 项目环境 -环境框架后端JDK1.8SpringBootmybatisPlus前端NodeJS16.0Vue2.0ElementPlus数据库MySQL8.0- 数据库设计 数据表备注banner轮播图表car用户汽…

树的表示——孩子兄弟表示法

从图中可以看出&#xff0c;树的每个结点&#xff0c;都有不确定的指向他们的孩子的节点&#xff0c;如果我们定义这样一个结构体来便是数的结构的话&#xff1a; struct TreeNode { int val; struct TreeNodep1; struct TreeNodep1; … }; 是不能够表示一棵树的&#xff0c;因…

可视化 | (一)数据基础及基本数据可视化方法

​ 文章目录 &#x1f4da;数据可视化的基本流程&#x1f4da;数据属性&#x1f4da;基本可视化图表类型&#x1f407;数据分析三规则&#x1f407;条形图&#xff08;Bar Chart&#xff09;&#x1f407;饼图&#xff08;Pie Chart&#xff09;&#x1f407;衡量易变性 (meas…

计算机网络(一):概述

参考引用 计算机网络微课堂-湖科大教书匠计算机网络&#xff08;第7版&#xff09;-谢希仁 1. 计算机网络在信息时代的作用 计算机网络已由一种通信基础设施发展成为一种重要的信息服务基础设施计算机网络已经像水、电、煤气这些基础设施一样&#xff0c;成为我们生活中不可或…

CleanMyMac X4.14.1最新和谐版下载

CleanMyMac一款macOS上非常经典的清理工具。它可以帮助用户清理垃圾文件、卸载无用应用程序、优化系统性能等。旨在帮助用户提高系统性能、释放磁盘空间并保持Mac的健康状态。 下面是CleanMyMac X软件的主要特点&#xff1a; 系统垃圾&#xff1a;清理您的系统来获得最大的性能…

CocosCreator3.8研究笔记(二十四)CocosCreator 动画系统-动画编辑器实操-关键帧实现动态水印动画效果

上一篇&#xff0c;我们介绍了动画编辑器相关功能面板说明&#xff0c;感兴趣的朋友可以前往阅读&#xff1a; CocosCreator3.8研究笔记&#xff08;二十三&#xff09;CocosCreator 动画系统-动画编辑器相关功能面板说明。 熟悉了动画编辑器的基础操作&#xff0c;那么再使用动…

Three.js:打造独一无二的3D模型可视化编辑神器!

前言 1.因为之前工作过的可视化大屏项目开发3d大屏组件模块需要用到Three.js来完成&#xff0c;其主功能是实现对3d模型的材质&#xff0c;灯光&#xff0c;背景&#xff0c;动画。等属性进行可视化的编辑操作以及模型编辑数据的存储和模型在大屏上面的拖拽显示 2.因为是第一…

不能显式拦截ajax请求的302响应?

记录工作中早该加深印象的一个小小小case&#xff1a;ajax请求不能显式拦截 302响应。 我们先来看一个常规的登录case: 1. 浏览器请求资源&#xff0c;服务器发现该请求未携带相关凭据&#xff08;cookie或者token&#xff09;2. 服务器响应302&#xff0c;并在响应头Location写…

2021-06-15 51单片机c语言秒表的仿真ISIS7 professional

缘由51单片机c语言秒表的仿真ISIS7 professional_嵌入式-CSDN问答 #include "REG52.h" sbit K1 P1^5; sbit K2 P1^6; sbit K3 P1^7; sbit K4 P1^4; sbit LED1P1^0; sbit LED2P1^1; sbit LED3P1^2; sbit LED4P1^3; bit k0; unsigned char code SmZiFu[]{63,6,91,…

IDT 一款自动化挖掘未授权访问漏洞的信息收集工具

IDT v1.0 IDT 意为 Interface detection&#xff08;接口探测) 项目地址: https://github.com/cikeroot/IDT/该工具主要的功能是对批量url或者接口进行存活探测&#xff0c;支持浏览器自动打开指定的url&#xff0c;避免手动重复打开网址。只需输入存在批量的url文件即可。 …

EM聚类(上):数据分析 | 数据挖掘 | 十大算法之一

⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ &#x1f434;作者&#xff1a;秋无之地 &#x1f434;简介&#xff1a;CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作&#xff0c;主要擅长领域有&#xff1a;爬虫、后端、大数据…

Polygon Miden:扩展以太坊功能集的ZK-optimized rollup

1. 引言 Polygon Miden定位为zkVM&#xff0c;定于2023年Q4上公开测试网。 zk、zkVM、zkEVM及其未来中指出&#xff0c;当前主要有3种类型的zkVM&#xff0c;括号内为其相应的指令集&#xff1a; mainstream&#xff08;WASM, RISC-V&#xff09;EVM&#xff08;EVM bytecod…

1.3 互联网的组成

思维导图&#xff1a; 前言&#xff1a; 我的笔记&#xff1a; #### 一、总览 - **互联网的结构**&#xff1a; - 具有全球覆盖和复杂的拓扑结构。 - 即便结构复杂&#xff0c;还是可以从工作方式上简化为两大部分&#xff1a;边缘部分和核心部分。 #### 二、边缘部分 -…

免费、丰富、便捷的资源论坛——Yiove论坛,包括但不限于阿里云盘、夸克云盘、迅雷云盘等等

引言 目前资源的数量达到了60000&#xff0c;六万多的资源意味着在这里几乎可以找到任何你想要的资源。 当然&#xff0c;资源并不是论坛的全部&#xff0c;其中还包括了技术交流、福利分享、最新资讯等等。 传送门&#xff1a;YiOVE论坛 - 一个有资源有交流&#xff0c;有一…