国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

首頁 php教程 PHP開發(fā) GIT 傳輸協(xié)定實現(xiàn)

GIT 傳輸協(xié)定實現(xiàn)

Nov 23, 2016 pm 02:18 PM

GIT 傳輸協(xié)定實作

在 GIT 的三種主流傳輸協(xié)定 HTTP SSH GIT 中,GIT 協(xié)定是最少被使用的協(xié)定(也就是 URL 以?git://?開始的協(xié)定)。 這是由於 git 協(xié)定的權限控制幾乎沒有,要麼全部可讀,要麼全部可寫,要麼全部可讀寫。所以對於程式碼託管平臺來說, git 協(xié)定的目的只是為了支援 公開專案的唯讀存取。

在 git 的各種傳輸協(xié)定中,git 協(xié)定無疑是最高效的,HTTP 受限於 HTTP 的特性,傳輸過程需要建構 HTTP 請求和回應。 如果是 HTTPS 還牽涉到加密解密。另外 HTTP 的超時設置,以及包體大小限制都會影響使用者體驗。

而 SSH 協(xié)定的效能問題主要集中在加密解密上。當然相對於使用者的資訊安全來說,這些代價都是可以接受。

git 協(xié)定實際上相當於 SSH 無加密無驗證,也就無從談起權限控制,但實際上程式碼託管平臺內(nèi)部的一些同步服務,如果使用 git 協(xié)定實現(xiàn),將會得到很大的效能提升。

傳輸協(xié)定規(guī)範

git 協(xié)定的技術文件可以從git 原始碼目錄的?Documentation/technical?找到,即?Packfile transfer protocols?建立TCP 連線後,git 用戶端率先發(fā)送請求體,請求格式基於BNF 的描述如下:

一個例子如下:

0033git-upload-pack /project.git

在 C 語言中,有 popen 函數(shù),可以創(chuàng)建一個進程,并將進程的標準輸出或標準輸入創(chuàng)建成一個文件指針,即?FILE*其他可以使用 C 函數(shù)的語言很多也提供了類似的實現(xiàn),比如 Ruby,基于 Ruby 的 git HTTP 服務器 grack 正是使用 的 popen,相比與其他語言改造的 popen,C 語言中 popen 存在了一些缺陷,比如無法同時讀寫,如果要輸出標準 錯誤,需要在命令參數(shù)中額外的將標準錯誤重定向到標準輸出。

在 musl libc 的中,popen 的實現(xiàn)如下:

FILE *popen(const char *cmd, const char *mode)
{
    int p[2], op, e;
    pid_t pid;
    FILE *f;
    posix_spawn_file_actions_t fa;

    if (*mode == 'r') {
        op = 0;
    } else if (*mode == 'w') {
        op = 1;
    } else {
        errno = EINVAL;
        return 0;
    }

    if (pipe2(p, O_CLOEXEC)) return NULL;
    f = fdopen(p[op], mode);
    if (!f) {
        __syscall(SYS_close, p[0]);
        __syscall(SYS_close, p[1]);
        return NULL;
    }
    FLOCK(f);

    /* If the child's end of the pipe happens to already be on the final
     * fd number to which it will be assigned (either 0 or 1), it must
     * be moved to a different fd. Otherwise, there is no safe way to
     * remove the close-on-exec flag in the child without also creating
     * a file descriptor leak race condition in the parent. */
    if (p[1-op] == 1-op) {
        int tmp = fcntl(1-op, F_DUPFD_CLOEXEC, 0);
        if (tmp < 0) {
            e = errno;
            goto fail;
        }
        __syscall(SYS_close, p[1-op]);
        p[1-op] = tmp;
    }

    e = ENOMEM;
    if (!posix_spawn_file_actions_init(&fa)) {
        if (!posix_spawn_file_actions_adddup2(&fa, p[1-op], 1-op)) {
            if (!(e = posix_spawn(&pid, "/bin/sh", &fa, 0,
                (char *[]){ "sh", "-c", (char *)cmd, 0 }, __environ))) {
                posix_spawn_file_actions_destroy(&fa);
                f->pipe_pid = pid;
                if (!strchr(mode, &#39;e&#39;))
                    fcntl(p[op], F_SETFD, 0);
                __syscall(SYS_close, p[1-op]);
                FUNLOCK(f);
                return f;
            }
        }
        posix_spawn_file_actions_destroy(&fa);
    }
fail:
    fclose(f);
    __syscall(SYS_close, p[1-op]);

    errno = e;
    return 0;
}

在 Windows Visual C++ 中,popen 源碼在?C:\Program Files (x86)\Windows Kits\10\Source\${SDKVersion}\ucrt\conio\popen.cpp?, 按照 MSDN 文檔說明,Windows 32 GUI 程序,即 subsystem 是 Windows 的程序,使用 popen 可能導致程序無限失去響應。

所以在筆者實現(xiàn) git-daemon 及其他 git 服務器時,都不會使用 popen 這個函數(shù)。

為了支持跨平臺和簡化編程,筆者在實現(xiàn) svn 代理服務器時就使用了 Boost Asio 庫,后來也用 Asio 實現(xiàn)過一個 git 遠程命令服務, 每一個客戶端與服務器連接后,服務器啟動程序,需要創(chuàng)建 3 條管道,分別是 子進程的標準輸入 輸出 錯誤,即 stdout stdin stderr, 然后注冊讀寫異步事件,將子進程的輸出與錯誤寫入到 socket 發(fā)送出去,讀取 socket 寫入到子進程的標準輸入中。

在 POSIX 系統(tǒng)中,boost 有一個文件描述符類?boost::asio::posix::stream_descriptor?這個類不能是常規(guī)文件,以前用 go 做 HTTP 前端 沒注意就 coredump 掉。

在 Windows 系統(tǒng)中,boost 有文件句柄類?boost::asio::windows::stream_handle?此處的文件應當支持隨機讀取,比如命名管道(當然 在 Windows 系統(tǒng)的,匿名管道實際上也是命名管道的一種特例實現(xiàn))。

以上兩種類都支持?async_read?async_write?,所以可以很方便的實現(xiàn)異步的讀取。

上面的做法,唯一的缺陷是性能并不是非常高,代碼邏輯也比較復雜,當然好處是,錯誤異常可控一些。

在 Linux 網(wǎng)絡通信中,類似與 git 協(xié)議這樣讀取子進程輸入輸出的服務程序的傳統(tǒng)做法是,將 子進程的 IO 重定向到 socket, 值得注意的是 boost 中 socket 是異步非阻塞的,然而,git 命令的標準輸入標準錯誤標準輸出都是同步的,所以在 fork 子進程之 前,需要將 socket 設置為同步阻塞,當 fork 失敗時,要設置回來。

socket_.native_non_blocking(false);

另外,為了記錄子進程是否異常退出,需要注冊信號 SIGCHLD 并且使用 waitpid 函數(shù)去等待,boost 就有?boost::asio::signal_set::async_wait?當然,如果你開發(fā)這樣一個服務,會發(fā)現(xiàn),頻繁的啟動子進程,響應信號,管理連接,這些操作才是性能的短板。

一般而言,Windows 平臺的 IO 并不能重定向到 socket,實際上,你如果使用 IOCP 也可以達到相應的效率。還有,Windows 的 socket API WSASocket WSADuplicateSocket 復制句柄 DuplicateHandle ,這些可以好好利用。

其他

對于非代碼托管平臺的從業(yè)者來說,上面的相關內(nèi)容可能顯得無足輕重,不過,網(wǎng)絡編程都是殊途同歸,最后核心理念都是類似的。關于 git-daemon 如果筆者有時間會實現(xiàn)一個跨平臺的簡易版并開源。


本網(wǎng)站聲明
本文內(nèi)容由網(wǎng)友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發(fā)現(xiàn)涉嫌抄襲或侵權的內(nèi)容,請聯(lián)絡admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅(qū)動的應用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)