<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    聶永的博客

    記錄工作/學習的點點滴滴。

    c_socket.io_server筆記之處理靜態文件

    緣由

    在編 寫純C語言版socket.io服務器 時,選擇了libev作為網絡基礎層代碼,可以離epoll模型遠一些,再說還可以避免單獨使用Epoll,寫出不易維護的多層嵌套代碼,聽說,有時Epoll出現一些“偽信號”小問題,沒有那么空閑精力,繞過之,選擇成熟度非常高的libev好了。
    有關libev的文章,中文資料不多,英文資料也不多。這里推薦三篇:
    - libev 設計分析
    - libev ev_io源碼分析
    - 官方文檔http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod,更為全面一些,閱讀時可以獲得較總體認知。

    這里把在編寫c_socket.io_server程中使用libev的一些地方做些筆記,記錄下來,也方便以后查閱。

    預備知識

    所有代碼的編寫、編譯、測試和運行等,都在Ubuntu下進行,另外實例嚴重依賴libev和http-parser HTTP解析庫。
    其它依賴,可以從https://github.com/yongboy/csocket.ioserver處下載。

    處理靜態文件

    這里設計一個靜態文件WEB服務器,非常簡單,僅僅滿足socket.io服務器最基本的需求,因此別苛求太多。但比網上很多大把類似文章多了一點寫入管道時緩沖區已滿問題的處理。
    這里簡單說一下處理靜態文件的思路。

    計算靜態文件路徑以及擴展名和內容類型

    char file_path[200]; 
    sprintf(file_path, "%s%s", static_folder, url_str);

    獲取文件內容和以及優先輸出響應頭部

        char file_path[200];
        sprintf(file_path, "%s%s", static_folder, url_str);

        int file = open(file_path, O_RDONLY);
        struct stat info;
        if (fstat(file, &info) == -1) {
            fprintf(stderr, "the file %s is NULL\n", file_path);
            write(client->fd, RESPONSE_404, strlen(RESPONSE_404));

            close(file);
            free_res(loop, client);

            return 0;
        }

        char file_ext[50];
        get_extension(file_path, file_ext);
        char content_type[50];
        get_content_type(file_ext, content_type);

        int file_len = info.st_size;
        char head_msg[200] = "";
        sprintf(head_msg, RESPONSE_TEMPLATE, content_type, file_len);
        write(client->fd, head_msg, strlen(head_msg));

    很顯然,這里引入fcntl.h頭部文件,調用fstat初始化stat結構,可判斷文件是否存在,以及文件大小等。

    讀取文件內容到緩沖區,循環寫入

    int read_count;
    int buf_size = 8 * 1024;//8096;
    char buffer[buf_size + 1];
    while ((read_count = read(file, buffer, buf_size)) > 0) {
    int bytes_left = read_count;
    char *ptr = buffer;
    int need_break = 0;
    while (bytes_left > 0) {
    ssize_t write_len = write(client->fd, ptr, bytes_left);

    if (write_len == -1) {
    fprintf(stderr, "write failed(errno = %d): %s\n", errno, strerror(errno));
    switch (errno) {
    case EAGAIN:
    case EINTR:
    case EINPROGRESS:
    fprintf(stderr, "now sleep 0.2s\n");
    ev_sleep(0.2);
    break;
    default:
    need_break = 1;
    break;
    }
    } else if (write_len == 0) {
    need_break = 1;
    fprintf(stderr, "write_len is zero, and break now\n");
    break;
    } else if (write_len < bytes_left) {
    bytes_left -= write_len;
    ptr += write_len;
    fprintf(stderr, "write client with something wrong wtih bytes_left = %d & write_len = %d and write the left data !\n", (int)bytes_left, (int)write_len);
    } else {
    break;
    }
    }

    if (need_break) {
    break;
    }
    }

    close(file);

    需要注意,構造的一個大約8K+1的緩沖區buffer,不是每次都可以正常完整輸出到socket對端,write輸出不完整,會返回-1,系統返回errno值,在errno = EAGAIN,EINTR,EINPROGRESS時,需要再次將緩沖區中尚未寫入的剩下數據再次寫入到請求端。這樣可以避免常見的半包、包不完整問題。

    關閉socket描述符,當前請求結束

    free_res(loop, client);
    

    請求完成,一定要記得關閉socket描述符,釋放相應資源等。 這樣一個較為完整的HTTP請求,靜態文件就處理完畢了。

    編譯運行

    先編譯:

    gcc staticserver.c -o staticserver ../include/libev.a ../include/http-parser/http_parser.o -lm

    運行之:

    ./static_server ../static

    命令輸入錯誤,如輸入靜態路徑為空,會報錯的,哈哈:

    Error: invald path parmeter

    Usage: ./static_server

    Example:
    ./staticserver ../static
    ./static
    server /home/yongboy/yourstaticfolder

    Enjoy it~

    測試一下吧

    curl -i http://192.168.190.150:8000/index.html

    在瀏覽器內,測試一下,支持圖片樣式等,完好顯示。

    需要注意,要傳入靜態文件目錄路徑,相對的路徑,或絕對的路徑,都是可以接受的。 最后,附上完整代碼:

    posted on 2013-03-25 16:46 nieyong 閱讀(2155) 評論(0)  編輯  收藏 所屬分類: socket.io

    公告

    所有文章皆為原創,若轉載請標明出處,謝謝~

    新浪微博,歡迎關注:

    導航

    <2013年3月>
    242526272812
    3456789
    10111213141516
    17181920212223
    24252627282930
    31123456

    統計

    常用鏈接

    留言簿(58)

    隨筆分類(130)

    隨筆檔案(151)

    個人收藏

    最新隨筆

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 曰批全过程免费视频观看免费软件| 亚洲Av高清一区二区三区| 美女扒开尿口给男人爽免费视频 | 久久99国产乱子伦精品免费| 亚洲精品自在在线观看| 国产99久久久久久免费看| 亚洲中文字幕成人在线| 一个人免费观看视频在线中文 | 美女视频黄.免费网址| 免费一级毛片一级毛片aa| 偷自拍亚洲视频在线观看| 免费亚洲视频在线观看| 免费一级全黄少妇性色生活片| 免费人成视频x8x8入口| yellow免费网站| 亚洲Av无码专区国产乱码DVD| 国产精品免费无遮挡无码永久视频| 久久综合日韩亚洲精品色| 91精品国产免费| 67194在线午夜亚洲| 青青草国产免费久久久91| 深夜特黄a级毛片免费播放| 亚洲欭美日韩颜射在线二| 全部免费毛片在线播放| 97久久国产亚洲精品超碰热| 日韩精品视频免费在线观看| 日韩在线视频免费| 亚洲AV无码久久精品色欲| 性xxxxx免费视频播放| 在线综合亚洲欧洲综合网站| 亚洲精品456播放| 少妇无码一区二区三区免费| 国产成人精品日本亚洲直接| 免费国产不卡午夜福在线| 97人妻精品全国免费视频 | 国产福利免费在线观看| 91国内免费在线视频| 亚洲a级在线观看| 久久久久国产亚洲AV麻豆| 精品国产免费人成电影在线观看 | 亚洲色图综合网站|