文件服务器架构

职责定义

  • 主线程

    • 命令行输出,管理员可管制服务端工作状态
  • 监听线程

    • 服务端启动后对客户端连贯进行监听的工作环境
  • 通信线程

    • 客户端连贯胜利后与服务端的数据交互环境

主线程

int main(int argc, char *argv){    if (argc >=2) {        DIR *dir = opendir(argv[1]);        if (dir != NULL) {            close(dir);            Run(argv[1]);        }    }     printf("Can not launch File Server, need a valid director as root.\n");    return 0;}
if (*line) {    char *cmd = FormatByChar(line, ' ');  // 此处的作用次要为去除前后空格    int done = 0;    for (i=0; i<DIM(g_handler); ++i) {        if (strcmp(g_handler[i].cmd, cmd) == 0) {            g_handler[i].handler(cmd);            done = 1;            break;        }    }        if (!done) {        printf("\'%s\' can NOT be parser!\n", cmd);    }    free(cmd);}

交互流程一

交互流程二

监护线程

static void *Server_Thread(void *arg){    while (TcpServer_IsValid(arg)) {        TcpClient *client = TcpServer_Accept(arg);        if (client &&(g_status != PAUSE)) {            pthread_t tid = 0;            pthread_create(&tid, NULL, Process_Thread, client);        } else {            TcpClient_Del(client);        }    }    printf("%s - Thread Exit : %p\n", __FCUNTION__, arg);    g_status = STOP;}

申请响应流程

通信流程

static void DoResp(TcpClient *client){    int len = TcpClient_Available(client);    if (len > 0) {        char *buf = malloc(len + 1);        TcpClient_RecvRaw(client, buf, len);        buf[len] = 0;        char resp[255] = {0};        // do process to create response        TcpClient_SendRaw(client, resp, strlen(resp));        TcpClient_Del(client);        free(buff);    }}

编程试验:实现申请响应

main.c

#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<pthread.h>#include <sys/types.h>#include <dirent.h>#include <sys/stat.h>#include <time.h>#include <fcntl.h>#include <string.h>#include "tcp_server.h"#include "tcp_client.h" #include "utility.h"#define BUF_SIZE 512typedef struct {    const char *cmd;    void (*handler)(const char *);}Handler;enum {STOP, RUN, PAUSE};static const volatile char *g_root = NULL;static volatile int g_status = STOP;static void DoResp(TcpClient *client){    int len = TcpClient_Available(client);    if (len > 0) {        char *buf = malloc(len + 1);        len = TcpClient_RecvRaw(client, buf, len);        if (len > 0) {            buf[len] = 0;            printf("%s - Request : %s\n", __FUNCTION__, buf);                char resp[255] = {0};            sscanf(buf, "GET %s HTTP\n", resp);  // 提取文件门路 !!            printf("%s - Req String: %s\n", __FUNCTION__, resp);            char* format = "HTTP/1.1 200 OK\r\n"                "Server:D.T. Http Server\r\n"                "Content-Length:%d\r\n"                "Content-Type:text/html\r\n"                "Connection:close\r\n"                "\r\n"                "%s";                                   sprintf(resp, format, strlen((const char*)g_root), g_root);                        TcpClient_SendRaw(client, resp, strlen(resp));                        TcpClient_Del(client);        }        free(buf);    }}static void *Process_Thread(void *arg){    while (TcpClient_IsValid(arg)) {        DoResp(arg);    }    printf("%s - Thread Exit : %p\n", __FUNCTION__, arg);    return arg;}static void *Server_Thread(void *arg){    while (TcpServer_IsValid(arg)) {        TcpClient *client = TcpServer_Accept(arg);        if (client && (g_status != PAUSE)) {            pthread_t tid = 0;            pthread_create(&tid, NULL, Process_Thread, client);        } else {            TcpClient_Del(client);        }    }    g_status = STOP;    return arg;}static void Start_Handler(const char *arg){    int err = 0;    if (g_status == STOP) {        TcpServer *server = TcpServer_New();        TcpServer_Start(server, 9000, 100);        if (TcpServer_IsValid(server)) {            pthread_t tid = 0;            err = pthread_create(&tid, NULL, Server_Thread, server);        } else {            err = 1;        }    }    if (!err) {        g_status = RUN;        printf("Server is OK!\n");    } else {        g_status = STOP;        printf("Server is failed!\n");    }}static void Pause_Handler(const char *arg){    if (g_status == RUN) {        g_status = PAUSE;        printf("Server is paused!\n");    } else {        printf("Server is NOT started!\n");    }}static void Exit_Handler(const char *arg){    exit(0);}static Handler g_handler[] = {    {"start", Start_Handler},    {"pause", Pause_Handler},    {"exit",  Exit_Handler}};static void Run(const char *root){    printf("File Server Demo @ D.T.Software\n");    g_root = root;    while (1) {        char line[BUF_SIZE] = {0};        int i = 0;        printf("D.T.Software @ Input >>> ");        fgets(line, sizeof(line) - 1, stdin);        line[strlen(line) - 1] = 0;        if (*line) {            char *cmd = FormatByChar(line, ' ');            int done = 0;            for (i-0; i<DIM(g_handler); ++i) {                if (strcmp (g_handler[i].cmd, cmd) == 0) {                    g_handler[i].handler(cmd);                    done = 1;                    break;                }            }            if (!done) {                printf("'\%s\' can NOT be parsed!\n", cmd);            }            free(cmd);        }    }}int main(int argc, char *argv[]){    if (argc >= 2) {        DIR *dir = opendir(argv[1]);        if (dir != NULL) {            closedir(dir);            Run(argv[1]);        }    }    printf("Can not launch File Server, need a valid directory as roots.\n");    return 0;}
输入:
tiansong@tiansong:~/Desktop/network/web$ ./a.out ./File Server Demo @ D.T.SoftwareD.T.Software @ Input >>> startServer is OK!D.T.Software @ Input >>> DoResp - Request : GET / HTTP/1.1Host: 192.168.112.165:9000Connection: keep-aliveCache-Control: max-age=0Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36 Edg/113.0.1774.50Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6DoResp - Req String: /1/2/3  // 提取到的文件门路 !!Process_Thread - Thread Exit : 0x7f77ac000c90DoResp - Request : GET /favicon.ico HTTP/1.1Host: 192.168.112.165:9000Connection: keep-aliveUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36 Edg/113.0.1774.50Accept: image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8Referer: http://192.168.112.165:9000/Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6DoResp - Req String: /favicon.icoProcess_Thread - Thread Exit : 0x7f77ac000b20
浏览器申请

思考

favivon.ico 是什么?如何解决?
如何创立浏览器中的文件展现页面?