国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

《TCP IP網(wǎng)絡(luò)編程》第十六章

這篇具有很好參考價值的文章主要介紹了《TCP IP網(wǎng)絡(luò)編程》第十六章。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

第 16 章 關(guān)于 I/O 流分離的其他內(nèi)容

?

16.1 分離 I/O 流

????????「分離 I/O 流」是一種常用表達。有 I/O 工具可區(qū)分二者,無論采用哪種方法,都可以認為是分離了 I/O 流。

2次 I/O 流分離:

  • 第一種是第 10 章的「TCP I/O 過程」分離。通
    shutdown(sock,SHUT_WR);
    過調(diào)用 fork 函數(shù)復(fù)制出一個文件描述符,以區(qū)分輸入和輸出中使用的文件描述符。雖然文件描述符本身不會根據(jù)輸入和輸出進行區(qū)分,但我們分開了 2 個文件描述符的用途,因此,這也屬于「流」的分離。
  • 第二種分離是在第 15 章。通過 2 次 fdopen 函數(shù)的調(diào)用,創(chuàng)建讀模式 FILE 指針(FILE 結(jié)構(gòu)體指針)和寫模式 FILE 指針。換言之,我們分離了輸入工具和輸出工具,因此也可視為「流」的分離。下面是分離的理由。

分離「流」的好處:

????????首先是第 10 章「流」的分離目的:

  • 通過分開輸入過程(代碼)和輸出過程降低實現(xiàn)難度
  • 與輸入無關(guān)的輸出操作可以提高速度

????????下面是第 15 章「流」分離的目的:

  • 為了將 FILE 指針按讀模式和寫模式加以區(qū)分
  • 可以通過區(qū)分讀寫模式降低實現(xiàn)難度
  • 通過區(qū)分 I/O 緩沖提高緩沖性能

「流」分離帶來的 EOF 問題:

????????第 7 章介紹過 EOF 的傳遞方法和半關(guān)閉的必要性。有一個語句:

shutdown(sock,SHUT_WR);

????????當(dāng)時說過調(diào)用 shutdown 函數(shù)的基于半關(guān)閉的 EOF 傳遞方法。第十章添加了半關(guān)閉的相關(guān)代碼。但是還沒有講采用 fdopen 函數(shù)怎么半關(guān)閉。那么是否是通過 fclose 函數(shù)關(guān)閉流呢?我們先試試:

????????服務(wù)端代碼:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define BUF_SIZE 1024

int main(int argc, char *argv[])
{
    int serv_sock, clnt_sock;
    FILE *readfp;
    FILE *writefp;

    struct sockaddr_in serv_adr, clnt_adr;
    socklen_t clnt_adr_sz;
    char buf[BUF_SIZE] = {
        0,
    };
    serv_sock = socket(PF_INET, SOCK_STREAM, 0);
    memset(&serv_adr, 0, sizeof(serv_adr));
    serv_adr.sin_family = AF_INET;
    serv_adr.sin_addr.s_addr = htonl(INADDR_ANY);
    serv_adr.sin_port = htons(atoi(argv[1]));
    bind(serv_sock, (struct sockaddr *)&serv_adr, sizeof(serv_adr));
    listen(serv_sock, 5);
    clnt_adr_sz = sizeof(clnt_adr);
    clnt_sock = accept(serv_sock, (struct sockaddr *)&clnt_adr, &clnt_adr_sz);

    readfp = fdopen(clnt_sock, "r");
    writefp = fdopen(clnt_sock, "w");

    fputs("FROM SERVER: Hi~ client? \n", writefp);
    fputs("I love all of the world \n", writefp);
    fputs("You are awesome! \n", writefp);
    fflush(writefp);

    fclose(writefp);
    fgets(buf, sizeof(buf), readfp);
    fputs(buf, stdout);
    fclose(readfp);
    return 0;
}

? ? ? ? 客戶端代碼:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define BUF_SIZE 1024

int main(int argc, char *argv[])
{
    int sock;
    char buf[BUF_SIZE];
    struct sockaddr_in serv_addr;

    FILE *readfp;
    FILE *writefp;

    sock = socket(PF_INET, SOCK_STREAM, 0);
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = inet_addr(argv[1]);
    serv_addr.sin_port = htons(atoi(argv[2]));

    connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
    readfp = fdopen(sock, "r");
    writefp = fdopen(sock, "w");

    while (1)
    {
        if (fgets(buf, sizeof(buf), readfp) == NULL)
            break;
        fputs(buf, stdout);
        fflush(stdout);
    }

    fputs("FROM CLIENT: Thank you \n", writefp);
    fflush(writefp);
    fclose(writefp);
    fclose(readfp);

    return 0;
}

運行結(jié)果:

《TCP IP網(wǎng)絡(luò)編程》第十六章,《TCPIP網(wǎng)絡(luò)編程》,tcp/ip,服務(wù)器,網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò)編程????????

????????從運行結(jié)果可以看出,服務(wù)端最終沒有收到客戶端發(fā)送的信息。

????????原因是:服務(wù)端代碼的?fclose(writefp);?這一句,完全關(guān)閉了套接字而不是半關(guān)閉。這才是這一章需要解決的問題。

16.2 文件描述符的的復(fù)制和半關(guān)閉

終止「流」時無法半關(guān)閉原因:

????????下面的圖描述的是服務(wù)端代碼中的兩個FILE 指針、文件描述符和套接字中的關(guān)系:

《TCP IP網(wǎng)絡(luò)編程》第十六章,《TCPIP網(wǎng)絡(luò)編程》,tcp/ip,服務(wù)器,網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò)編程

????????從圖中可以看到,兩個指針都是基于同一文件描述符創(chuàng)建的。因此,針對于任何一個 FILE 指針調(diào)用 fclose 函數(shù)都會關(guān)閉文件描述符,如圖所示:

《TCP IP網(wǎng)絡(luò)編程》第十六章,《TCPIP網(wǎng)絡(luò)編程》,tcp/ip,服務(wù)器,網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò)編程

????????那如何進入可以進入但是無法輸出的半關(guān)閉狀態(tài)呢?如下圖所示:

《TCP IP網(wǎng)絡(luò)編程》第十六章,《TCPIP網(wǎng)絡(luò)編程》,tcp/ip,服務(wù)器,網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò)編程

????????只需要創(chuàng)建 FILE 指針前先復(fù)制文件描述符即可。復(fù)制后另外創(chuàng)建一個文件描述符,然后利用各自的文件描述符生成讀模式的 FILE 指針和寫模式的 FILE 指針。這就為半關(guān)閉創(chuàng)造好了環(huán)境,因為套接字和文件描述符具有如下關(guān)系:?

????????銷毀所有文件描述符候才能銷毀套接字。

????????也就是說,針對寫模式 FILE 指針調(diào)用 fclose 函數(shù)時,只能銷毀與該 FILE 指針相關(guān)的文件描述符,無法銷毀套接字,如下圖:

《TCP IP網(wǎng)絡(luò)編程》第十六章,《TCPIP網(wǎng)絡(luò)編程》,tcp/ip,服務(wù)器,網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò)編程

????????那么調(diào)用 fclose 函數(shù)候還剩下 1 個文件描述符,因此沒有銷毀套接字。那此時的狀態(tài)是否為半關(guān)閉狀態(tài)?不是!只是準(zhǔn)備好了進入半關(guān)閉狀態(tài),而不是已經(jīng)進入了半關(guān)閉狀態(tài)。仔細觀察,還剩下一個文件描述符。而該文件描述符可以同時進行 I/O 。因此,不但沒有發(fā)送 EOF ,而且仍然可以利用文件描述符進行輸出。?

復(fù)制文件描述符:

????????與調(diào)用 fork 函數(shù)不同,調(diào)用 fork 函數(shù)將復(fù)制整個進程,此處討論的是同一進程內(nèi)完成對描述符的復(fù)制。如圖:

《TCP IP網(wǎng)絡(luò)編程》第十六章,《TCPIP網(wǎng)絡(luò)編程》,tcp/ip,服務(wù)器,網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò)編程

????????復(fù)制完成后,兩個文件描述符都可以訪問文件,但是編號不同。?

dup 和 dup2:

????????下面給出文件描述符的復(fù)制方法:

#include <unistd.h>
int dup(int fildes);
int dup2(int fildes, int fildes2);
/*
成功時返回復(fù)制的文件描述符,失敗時返回 -1
fildes : 需要復(fù)制的文件描述符
fildes2 : 明確指定的文件描述符的整數(shù)值。
*/

????????dup2 函數(shù)明確指定復(fù)制的文件描述符的整數(shù)值。向其傳遞大于 0 且小于進程能生成的最大文件描述符值時,該值將成為復(fù)制出的文件描述符值。下面是dup的代碼示例:

#include <stdio.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
    int cfd1, cfd2;
    char str1[] = "Hi~ \n";
    char str2[] = "It's nice day~ \n";

    cfd1 = dup(1);        //復(fù)制文件描述符 1
    cfd2 = dup2(cfd1, 7); //再次復(fù)制文件描述符,定為數(shù)值 7

    printf("fd1=%d , fd2=%d \n", cfd1, cfd2);
    write(cfd1, str1, sizeof(str1));
    write(cfd2, str2, sizeof(str2));

    close(cfd1);
    close(cfd2); //終止復(fù)制的文件描述符,但是仍有一個文件描述符
    write(1, str1, sizeof(str1));
    close(1);
    write(1, str2, sizeof(str2)); //無法完成輸出
    return 0;
}

? ? ? ? ?運行結(jié)果:

《TCP IP網(wǎng)絡(luò)編程》第十六章,《TCPIP網(wǎng)絡(luò)編程》,tcp/ip,服務(wù)器,網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò)編程

????????復(fù)制文件描述符后「流」的分離?:

????????下面更改sep_clnt.c和sep_serv.c???可以使得讓它正常工作,正常工作是指通過服務(wù)器的半關(guān)閉狀態(tài)接收客戶端最后發(fā)送的字符串。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define BUF_SIZE 1024

int main(int argc, char *argv[])
{
    int serv_sock, clnt_sock;
    FILE *readfp;
    FILE *writefp;

    struct sockaddr_in serv_adr, clnt_adr;
    socklen_t clnt_adr_sz;
    char buf[BUF_SIZE] = {
        0,
    };
    serv_sock = socket(PF_INET, SOCK_STREAM, 0);
    memset(&serv_adr, 0, sizeof(serv_adr));
    serv_adr.sin_family = AF_INET;
    serv_adr.sin_addr.s_addr = htonl(INADDR_ANY);
    serv_adr.sin_port = htons(atoi(argv[1]));
    bind(serv_sock, (struct sockaddr *)&serv_adr, sizeof(serv_adr));
    listen(serv_sock, 5);
    clnt_adr_sz = sizeof(clnt_adr);
    clnt_sock = accept(serv_sock, (struct sockaddr *)&clnt_adr, &clnt_adr_sz);

    readfp = fdopen(clnt_sock, "r");
    writefp = fdopen(dup(clnt_sock), "w"); //復(fù)制文件描述符

    fputs("FROM SERVER: Hi~ client? \n", writefp);
    fputs("I love all of the world \n", writefp);
    fputs("You are awesome! \n", writefp);
    fflush(writefp);

    shutdown(fileno(writefp), SHUT_WR); //對 fileno 產(chǎn)生的文件描述符使用 shutdown 進入半關(guān)閉狀態(tài)
    fclose(writefp);

    fgets(buf, sizeof(buf), readfp);
    fputs(buf, stdout);
    fclose(readfp);
    return 0;
}

? ? ? ? 運行結(jié)果:

《TCP IP網(wǎng)絡(luò)編程》第十六章,《TCPIP網(wǎng)絡(luò)編程》,tcp/ip,服務(wù)器,網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò)編程?

? ? ? ? ?運行結(jié)果證明了 服務(wù)器端在半關(guān)閉狀態(tài)下向客戶端發(fā)送了EOF。文章來源地址http://www.zghlxwxcb.cn/news/detail-647247.html

到了這里,關(guān)于《TCP IP網(wǎng)絡(luò)編程》第十六章的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 《TCP IP 網(wǎng)絡(luò)編程》第十五章

    《TCP IP 網(wǎng)絡(luò)編程》第十五章

    ?標(biāo)準(zhǔn) I/O 函數(shù)的兩個優(yōu)點: ????????除了使用 read 和 write 函數(shù)收發(fā)數(shù)據(jù)外,還能使用標(biāo)準(zhǔn) I/O 函數(shù)收發(fā)數(shù)據(jù)。下面是標(biāo)準(zhǔn) I/O 函數(shù)的兩個優(yōu)點: 標(biāo)準(zhǔn) I/O 函數(shù)具有良好的移植性 標(biāo)準(zhǔn) I/O 函數(shù)可以利用緩沖提高性能 ????????創(chuàng)建套接字時,操作系統(tǒng)會準(zhǔn)備 I/O 緩沖。 此緩

    2024年02月14日
    瀏覽(25)
  • 《TCP IP網(wǎng)絡(luò)編程》第十三章

    《TCP IP網(wǎng)絡(luò)編程》第十三章

    Linux 中的 send recv: ?????????send 函數(shù)定義: ????????recv 函數(shù)的定義: ????????send 和 recv 函數(shù)的最后一個參數(shù)是收發(fā)數(shù)據(jù)的可選項,該選項可以用位或(bit OR)運算符(| 運算符)同時傳遞多個信息。send recv 函數(shù)的可選項意義: MSG_OOB:發(fā)送緊急消息?: ????

    2024年02月15日
    瀏覽(23)
  • TCP/IP網(wǎng)絡(luò)編程 第十七章:優(yōu)于select的epoll

    select復(fù)用方法其實由來已久,因此,利用該技術(shù)后,無論如何優(yōu)化程序性能也無法同時接入上百個客戶端(當(dāng)然,硬件性能不同,差別也很大)。這種select方式并不適合以Web服務(wù)器端開發(fā)為主流的現(xiàn)代開發(fā)環(huán)境,所以要學(xué)習(xí)Linux平臺下的epoll。 基于select的I/O復(fù)用技術(shù)速度慢的原

    2024年02月16日
    瀏覽(29)
  • TCP/IP網(wǎng)絡(luò)編程 第十九章:Windows平臺下線程的使用

    要想掌握Windows平臺下的線程,應(yīng)首先理解“內(nèi)核對象”(Kernel Objects)的概念。如果僅介紹Windows平臺下的線程使用技巧,則可以省略相對陌生的內(nèi)核對象相關(guān)內(nèi)容。但這并不能使各位深入理解Windows平臺下的線程。 內(nèi)核對象的定義 操作系統(tǒng)創(chuàng)建的資源有很多種,如進程、線程

    2024年02月16日
    瀏覽(30)
  • TCP/IP網(wǎng)絡(luò)編程 第十五章:套接字和標(biāo)準(zhǔn)I/O

    TCP/IP網(wǎng)絡(luò)編程 第十五章:套接字和標(biāo)準(zhǔn)I/O

    標(biāo)準(zhǔn)I/O函數(shù)的兩個優(yōu)點 將標(biāo)準(zhǔn)I/O函數(shù)用于數(shù)據(jù)通信并非難事。但僅掌握函數(shù)使用方法并沒有太大意義,至少應(yīng)該 了解這些函數(shù)具有的優(yōu)點。下面列出的是標(biāo)準(zhǔn)I/O函數(shù)的兩大優(yōu)點: □標(biāo)準(zhǔn)I/O函數(shù)具有良好的移植性(Portability) □標(biāo)準(zhǔn)I/O函數(shù)可以利用緩沖提高性能。 關(guān)于移植性無需

    2024年02月16日
    瀏覽(96)
  • 嵌入式學(xué)習(xí)第二十六天?。ňW(wǎng)絡(luò)傳輸:TCP編程)

    嵌入式學(xué)習(xí)第二十六天?。ňW(wǎng)絡(luò)傳輸:TCP編程)

    ? ? ? ? socket ? -? connect? -? send? -? recv ? -? close ? ? ? ? socket ? -? bind ? -? listen ? -? accept ? - recv ? -? send ? -? close ????????1. connect: ? ? ? ? ? ? ? 功能: 發(fā)送鏈接請求 ? ? ? ? ? ? ? 參數(shù): ? ? ? ? ? ? ? ? ? sockfd: 套接字文件描述符 ? ? ? ? ? ? ? ? ?

    2024年03月09日
    瀏覽(39)
  • 突破編程_C++_網(wǎng)絡(luò)編程(TCPIP 四層模型(概述))

    TCP/IP 協(xié)議,全稱為 Transmission Control Protocol/Internet Protocol,中文名為傳輸控制協(xié)議/因特網(wǎng)互聯(lián)協(xié)議,又名網(wǎng)絡(luò)通訊協(xié)議。這是 Internet 最基本的協(xié)議,也是 Internet 國際互聯(lián)網(wǎng)絡(luò)的基礎(chǔ)。它主要由網(wǎng)絡(luò)層的 IP 協(xié)議和傳輸層的 TCP 協(xié)議組成,定義了電子設(shè)備如何連入因特網(wǎng),以及數(shù)

    2024年04月08日
    瀏覽(38)
  • 突破編程_C++_網(wǎng)絡(luò)編程(TCPIP 四層模型(傳輸層))

    在 TCP/IP 四層模型中,傳輸層位于網(wǎng)絡(luò)層之上和應(yīng)用層之下,負責(zé)在源主機和目標(biāo)主機之間提供端到端的可靠數(shù)據(jù)傳輸服務(wù)。傳輸層的主要功能與作用體現(xiàn)在以下幾個方面: 分段與重組:由于網(wǎng)絡(luò)層的數(shù)據(jù)包大小有限制(如 IP 數(shù)據(jù)包的最大長度為 65535 字節(jié)),而應(yīng)用層的數(shù)

    2024年04月09日
    瀏覽(32)
  • 《TCP IP網(wǎng)絡(luò)編程》

    《TCP IP網(wǎng)絡(luò)編程》

    ? ? ? ? 2023.6.28 正式開始學(xué)習(xí)網(wǎng)絡(luò)編程。 每一章每一節(jié)的筆記都會記錄在博客中以便復(fù)習(xí)。 ? ? ? ? 網(wǎng)絡(luò)編程又叫套接字編程。所謂網(wǎng)絡(luò)編程,就是編寫程序使兩臺連網(wǎng)的計算機相互交換數(shù)據(jù)。 為什么叫套接字編程? 我們平常將插頭插入插座上就能從電網(wǎng)中獲取電力,同

    2024年02月11日
    瀏覽(25)
  • TCP/IP網(wǎng)絡(luò)編程(三)

    TCP/IP網(wǎng)絡(luò)編程(三)

    多播(Multicast)方式的數(shù)據(jù)傳輸是 基于 UDP 完成的 。因此 ,與 UDP 服務(wù)器端/客戶端的實現(xiàn)方式非常接近。區(qū)別在于,UDP 數(shù)據(jù)傳輸以單一目標(biāo)進行,而多播數(shù)據(jù) 同時傳遞到加入(注冊)特定組的大量主機 。換言之, 采用多播方式時,可以同時向多個主機傳遞數(shù)據(jù) 。 14.1.1 多

    2024年02月03日
    瀏覽(36)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包