1. 程式人生 > >Linux網絡編程(3)——多進程、多線程

Linux網絡編程(3)——多進程、多線程

ssh pri turn null client 技術分享 malloc tle ()


在我的技術分享裏面已經介紹了linux以下c的進程、線程接口,這裏就不做過多闡述了。


多進程

這裏多進程採用傳統的多進程模型。每當有client發來的連接時創建一個進程來處理連接,一個子進程相應一個連接。

有了上篇單一進程的基礎,此處僅僅做簡單的改動便能夠實現。

    while(1){
        clientfd = Accept(servfd, (struct sockaddr*)&cliaddr, &clientlen);
        host = Gethostbyaddr((const char*)&cliaddr.sin_addr.s_addr, sizeof(cliaddr.sin_addr.s_addr), AF_INET);
        printf("server connect to host: %s %s\n",host->h_name, inet_ntoa(cliaddr.sin_addr));
        if ((child_pid = Fork()) == 0){
            Close(servfd);
            echo(clientfd);
            Close(clientfd);
        }
        Close(clientfd);
    }
僅僅須要在while裏面加入進程的創建就可以,然後在子進程裏先關閉父進程的監聽套接字。

當然。不要忘了在上面加入Fork錯誤處理的包裹函數(在Fork一節中已講到)。

void error_msg(char *msg){
    perror(msg);
    exit(0);
}

int Fork(){
    pid_t pid;
    if ( ( pid = fork() ) < 0 )
        error_msg("fork failed");
    return pid;
}

執行結果:

client:

技術分享

server:

技術分享

多線程

線程和進程在非常多方面是相通的,仿照上面的多進程的傳統模型。不難實現多線程的傳統模型。

依舊是在while裏面做簡單的改動就可以。

        clientfd = (int*)malloc(sizeof(int));
        *clientfd = Accept(servfd, (struct sockaddr*)&cliaddr, &clientlen);
        host = Gethostbyaddr((const char*)&cliaddr.sin_addr.s_addr, sizeof(cliaddr.sin_addr.s_addr), AF_INET);
        printf("server connect to host: %s %s\n",host->h_name, inet_ntoa(cliaddr.sin_addr));
        Pthread_create(&tid, NULL, &thread, clientfd);
        Close(*clientfd);

使用malloc是為了避免因為多線程訪問了同樣的clientfd從而出現無法預估的後果,全部手動分配。

線程函數為

void *thread(void* arg){
    int clientfd = *((int*)arg);
    free(arg);
    Pthread_detach(pthread_self());
    echo(clientfd);
    close(clientfd);
    return NULL;
}

執行結果:

這段代碼有個問題,clientfd傳入線程之後。arg指針沒有接收到值,指在了一個無法訪問的地方(gdb顯示值為0x00),百思不得其解。

(原理非常easy,遇到的問題先記錄下,假設有人知道錯在哪裏希望能指正出來。。

環境 ubuntu 64位,編譯器gcc)


Linux網絡編程(3)——多進程、多線程