青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

依舊的博客

技術學習

C++博客 首頁 新隨筆 聯系 聚合 管理
  17 Posts :: 1 Stories :: 2 Comments :: 0 Trackbacks

1. 客戶-服務器通信中的基本問題

客戶和服務器通信是為了使用服務,為此在傳輸機制的基礎上設計協議,通過對通信行為的規范,實現通信的目的,并解決傳輸中的問題。

傳輸機制通常由下層協議提供,根據不同的通信需要選擇不同的下層協議,這是一個基本的問題。對應用協議來說,可用的傳輸機制有可靠連接的字節流類型和不可靠無連接的數據報類型。

服務器處理大量客戶的請求,從而并發是服務器的一個基本問題,如何處理這個問題也取決于通信需要。處理方式上,服務器可以是循環的或并發的,并發服務器有多種實現方式(異步I/O,多線程和多進程)。

一件事情能無重復地連續進行,通常會獲得更好的效率,這要求主體始終知道當前的狀態。一次通信過程的連續性取決于通信雙方,它們都要知道通信進行的狀態。這對客戶一般不成問題,但服務器要和大量客戶通信,不一定能為每個客戶的每次通信保存狀態。如果服務器是有狀態的,那么就更快地計算響應,減少通信的數據量。但是傳輸和客戶的故障使有狀態服務器面臨很大問題,當傳輸不可靠(報文重復,丟失,亂序)時,服務器維護的狀態會和客戶失去一致,一個不斷崩潰重啟的客戶會造成狀態信息不能發揮作用,而維護開銷卻極大增加。

這就提出了客戶-服務器通信中的三個基本問題,它們的解決方案都取決于實際需要,客戶-服務器通信中有哪些情況的需要呢?

  • 是否要求可靠傳輸;
  • 是否需要服務器進行大量處理。對循環服務器進行分析可以知道,需要大量處理的通信用循環方案可能會丟失請求,用并發方案還可以提高服務器資源利用率,改善性能,只要少量處理的通信則無法忍受開銷大的解決方案。
  • 在局域網還是互聯網環境下,局域網中傳輸很少出錯,互聯網環境則不然;


通常根據前兩個基本問題把服務器實現分為四種類型,它們的適用范圍如下:

  • 循環無連接服務器,少量處理的通信時,并且在局域網中或不要求可靠傳輸。這種做法主要是為了避免開銷。
  • 循環連接服務器,較少用,主要是循環的方式不夠高效,因為連接有一定開銷,響應時間可能不低。在少量處理并要求可靠性的情況下使用。
  • 并發無連接服務器,很少用,因為要給每個請求開線程,開銷太大。在不要求可靠性的情況下,如果線程開銷遠小于計算響應開銷,或者并發可以讓各請求的I/O并行,或者循環方案會丟失請求時可以考慮。
  • 并發連接服務器,常用。


2. winsock基本函數的使用

winsock的基本函數有WSAStartup(),WSACleanup(),socket(),closesocket(),bind(),listen(),accept(), connect(),send()和recv()。

使用這些函數,客戶端的大概算法是,

  1.  調用WSAStartup()初始化winsock庫。
  2.  調用socket()創建套接字,返回套接字描述符s。
  3.  指定遠程套接字地址sa,對s調用connect(),向sa標識的服務進程請求連接。
  4.  連接成功后,對s調用send()發送請求,調用recv()接收響應,如此反復直到完成任務。
  5.  對s調用closesocket()關閉連接。
  6.  不再發起連接處理新的任務時,調用WSACleanup()釋放winsock庫。

服務器端的大概算法是,

  1. 調用WSAStartup()初始化winsock庫。
  2. 調用socket()創建套接字,返回套接字描述符s。
  3. 對s調用bind(),將其綁定到本地的套接字sa。
  4. 調用listen(),將s置為被動模式。此時開始偵聽客戶端的連接請求,將其放入一個隊列。
  5. 對s調用accept(),即從請求隊列中取出一項,接受該連接后返回一個新的套接字描述符s',以及對應客戶端的套接字地址sa'。
  6. 對s'調用recv()接收請求,調用send()發送響應,如此反復直到完成任務。
  7. 對s'調用closesocket()關閉該連接。
  8. 重復5到7的過程。
  9. 從8退出后,調用WSACleanup()釋放winsock庫。

有以下幾點需要進一步說明,

1). 客戶端調用connect()和服務器端調用accept()成功后將在客戶進程和服務器進程之間建立一個TCP連接。連接兩端的每個套接字描述符都包含一個本地端點地址和一個遠程端點地址。所以在使用連接套接字發送數據時不用指示目的地址。

2). 多宿主主機的IP地址選擇問題。從上面的算法容易提出這樣的問題,為什么客戶端在使用套接字時不綁定端點地址?通常的主機只有一個IP,但是多宿主主機有多個IP地址,在這種情況下,客戶端為套接字指定的IP可能與實際發送時經過的IP不符,所以允許客戶端不指定套接字地址,而由TCP/IP軟件在實際發送時指定IP,同時選擇一個未用過的端口號,這正是在connect()調用中完成的。那么服務器端就不存在同樣的情況嗎?不是,在它調用bind()時指定一個套接字地址,其端口部分采用應用協議的熟知端口,而IP地址部分有著同樣的問題。為此定義了一個代表統配地址的常量INADDR_ANY,用它指示IP地址部分。實際使用的IP仍然是由TCP/IP軟件分配。

3). TCP為一個連接的發送端和接收端各維護一個緩沖區。當發送端緩沖區滿的時候,send()調用會阻塞,在接收端緩沖區為空的時候,recv()調用會阻塞。為什么要在通信進程和TCP連接之間維護一個間接層呢?可能是為了在一端有多個進程要使用信道的情況下,在多個進程之間進行信道分配的協調。比如在發送端,信道傳輸數據時send()調用可以繼續執行,多個進程的send()調用同緩沖區打交道,彼此影響不大,因為讀寫緩沖區速度很快,而信道同緩沖區打交道,這時可以對各進程的發送數據進行協調,實現公平的信道分配。另外,在TCP中有滑動窗口概念,是用于流量控制的,前述緩沖區和滑動窗口有什么關系?我現在不太清楚。

4). 套接字的關閉問題。在客戶機和服務器通過TCP連接完成數據交換后,有一個安全關閉的問題。一方面,服務器不能關閉連接,因為客戶機可能還有請求,另一方面,客戶機雖然知道何時不再請求,但是它不知道服務器的響應何時發送完,因為有些應用協議的響應數據量不確定。為此采用部分關閉的辦法,雖然連接是雙向的,但是允許在一個方向上關閉它,當客戶端不再請求時,可以部分關閉連接,使服務器收到一個信號,如果響應發送完了,服務器就可以關閉連接,此時連接被完全關閉

3. 套接字接口中的端點地址

端點地址用來表示通信的進程,是傳輸層協議及其套接字接口中的重要概念。不同的協議族可以用不同方式表示端點地址,一個協議族還可以有多個地址族,每個地址族的地址格式不同。TCP/IP只有一個地址族,它的端點地址包括一個32位IP地址和一個16位端口號。在協議族和地址族的基礎上,套接字接口用更為具體的結構來表示端點地址。

套接字是一種適用于多個協議族的接口,并允許一個協議族使用多個地址族。TCP/IP協議族及其唯一地址族的標識分別是PF_INET和AF_INET。由于套接字接口的通用性,它提供一個通用的地址結構,其格式為(地址族,該族中的套接字地址)。套接字作為一個接口標準,可以有不同實現,以下我們只討論windows套接字。

如下定義的sockaddr實現了前述通用地址結構,

// winsock2.h

struct sockaddr {
        u_short sa_family;              /* address family */
        char    sa_data[14];            /* up to 14 bytes of direct address */
};

sockaddr的通用性是相對的,某些地址族不適合這個結構。

盡管sockaddr適合于TCP/IP協議族,但是winsock還定義了TCP/IP專用的地址格式,

// winsock2.h

struct sockaddr_in {
        short   sin_family;
        u_short sin_port;
        struct  in_addr sin_addr;
        char    sin_zero[8];
};

sin_family域取值恒為AF_INET。其中的in_addr結構表示IP地址,定義如下,

//winsock2.h

struct in_addr {
        union {
                struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
                struct { u_short s_w1,s_w2; } S_un_w;
                u_long S_addr;
        } S_un;
#define s_addr  S_un.S_addr
                                /* can be used for most TCP & IP code */
#define s_host  S_un.S_un_b.s_b2
                                /* host on imp */
#define s_net   S_un.S_un_b.s_b1
                                /* network */
#define s_imp   S_un.S_un_w.s_w2
                                /* imp */
#define s_impno S_un.S_un_b.s_b4
                                /* imp # */
#define s_lh    S_un.S_un_b.s_b3
                                /* logical host */
};

為了保證軟件的可移植性與可維護性,訪問TCP/IP的代碼不應使用sockaddr。只使用TCP/IP的應用程序可以只使用sockaddr_in,而永遠不用sockaddr。

4. winsock程序實例

《vc6技術內幕》的例程ex34a包括一個web服務器和三個客戶,服務器用winsock實現,一個客戶用winsock,另兩個用wininet。我們以winsock實現的服務器和客戶為例。

CBlockingSocket對各接口函數進行封裝,使它們的調用可以統一報錯。把錯誤檢查和函數調用一起封裝可以避免每次調用這些函數時都檢錯。為統一報錯,采用了異常機制,在檢出錯誤后拋出異常,然后統一進行異常處理。異常機制使我們可以把錯誤檢查和錯誤處理分開,檢查必須是分散的,但是處理可以適當集中,使代碼簡化。

CHttpBlockingSocket根據接收http報文的特點對CBlockingSocket進行了擴展。成員函數ReadHttpHeaderLine()可以從TCP連接中按行接收字符(它引入了一個緩沖區,緩沖區中收到的字符構成一行后再輸出。該緩沖區的長度需要能夠容納每一行字符,溢出時報錯。接收輸出行的緩沖區也可能長度不足,這時接收的數據不足一行,在調用ReadHttpHeaderLine()時要注意這一點),ReadHttpResponse()用于接收首部行之后所有的響應,當調用者提供的緩沖區不足時會報錯。緩沖區不足的情況都是在CBlockingSocket::Receive()函數中檢測到的,該函數調用以上層次中的代碼按照正常情況編寫。

CSockAddr是一個與sockaddr_in同樣用途的類,但是用法更方便。winsock函數使用的端點地址結構是sockaddr,sockaddr_in本身用來代替它,所以CSockAddr需要能夠替代sockaddr。sockaddr可能用在傳值或傳址參數中,CSockAddr必須在邏輯上和存儲上都和sockaddr有等價性,并實現有關強制類型轉換。CSockAddr還實現了和sockaddr, sockaddr_in互相轉換的成員函數,因為一種結構很難在所有情況下都好用,新結構也需要和舊結構保持兼容。

 

本例中采用服務器關閉套接字的辦法,因為每次連接只處理一個請求。

參考:

《用TCP/IP進行網際互聯第三卷(windows套接字版)》/清華出版社

《vc6技術內幕 5th ed》/希望電子出版社

posted on 2006-05-02 12:46 依舊的博客 閱讀(2299) 評論(0)  編輯 收藏 引用 所屬分類: 編程
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久国产视频网| 久久婷婷成人综合色| 久久久久久久久蜜桃| 一区二区av| 一区二区三区久久网| 最新国产乱人伦偷精品免费网站| 伊人影院久久| 亚洲国产99| 一区二区欧美激情| 亚洲欧美日韩一区| 久久久久国产一区二区三区四区 | 欧美日韩国产综合新一区| 久热精品视频在线观看| 欧美巨乳在线| 国产日韩精品在线观看| 一区二区三区在线视频免费观看| 在线免费观看欧美| 亚洲视频免费观看| 久久久久久婷| 亚洲人成在线播放| 亚洲国产成人在线| 亚洲图片欧洲图片av| 欧美与欧洲交xxxx免费观看 | 亚洲网站在线观看| 久久视频免费观看| 亚洲乱码国产乱码精品精可以看| 国产精品高潮呻吟久久| 欧美视频一区二区三区…| 欧美电影免费观看| 国产精品极品美女粉嫩高清在线 | 一本色道久久综合亚洲91| 性欧美精品高清| 欧美黄色小视频| 国产亚洲一级高清| 亚洲永久在线| 一区精品久久| 午夜在线视频观看日韩17c| 欧美成人一区二免费视频软件| 国产精品99久久久久久久女警 | 亚洲黄色免费网站| 亚洲女同同性videoxma| 欧美激情第3页| 韩日欧美一区二区三区| 亚洲视频自拍偷拍| 欧美激情一二区| 久久久国产一区二区| 国产麻豆日韩| 亚洲一区二区三区精品在线观看| 美乳少妇欧美精品| 欧美专区福利在线| 国产日韩欧美高清| 香蕉免费一区二区三区在线观看 | 日韩视频在线永久播放| 男同欧美伦乱| 亚洲精品1234| 欧美大片在线看| 久久精视频免费在线久久完整在线看| 国产精一区二区三区| 亚洲一级黄色片| 99天天综合性| 99国产精品国产精品毛片| 久久琪琪电影院| 精东粉嫩av免费一区二区三区| 欧美在线一区二区| 欧美一区二区三区免费视频| 国产婷婷精品| 久久久久久久成人| 欧美在线视频一区| 国产综合香蕉五月婷在线| 久久久91精品国产| 久久久久久久一区| 黄色一区二区三区| 久久尤物视频| 欧美大片国产精品| 一区二区三区不卡视频在线观看 | 激情综合久久| 久热re这里精品视频在线6| 久久精品官网| 亚洲电影免费观看高清完整版在线观看 | 欧美激情综合亚洲一二区| 亚洲精品一级| av成人动漫| 国产午夜精品久久| 国产喷白浆一区二区三区| 欧美一区二区视频观看视频| 午夜精品视频在线| 国产一区二区三区久久久| 久久久久久久一区| 欧美精品在线网站| 欧美一区三区二区在线观看| 久久久久久综合| 亚洲午夜久久久久久久久电影网| 午夜性色一区二区三区免费视频| 在线看无码的免费网站| 日韩视频精品在线观看| 国产色综合网| 亚洲国产三级| 国产日本欧美一区二区| 欧美激情欧美狂野欧美精品 | 久热精品视频在线观看| 亚洲午夜精品一区二区三区他趣| 欧美一级日韩一级| 在线免费高清一区二区三区| 99re这里只有精品6| 激情欧美一区二区| 一区二区欧美在线| 最新日韩在线| 欧美主播一区二区三区美女 久久精品人 | 亚洲一区欧美激情| 久久亚洲精品一区二区| 欧美日韩免费| 欧美资源在线观看| 欧美日韩精选| 欧美激情二区三区| 国外成人在线| 亚洲一区二区网站| 亚洲精品少妇网址| 久久免费国产精品| 久久久91精品国产| 国产欧美亚洲一区| 一区二区三区欧美在线| 亚洲高清资源| 久久精品一区二区| 欧美中文字幕精品| 欧美日韩亚洲一区二区三区在线| 亚洲国产另类精品专区| 99ri日韩精品视频| 一区二区三区高清| 欧美黄色一级视频| 亚洲大胆av| 1204国产成人精品视频| 久久成人免费日本黄色| 欧美一区=区| 国产女精品视频网站免费| 亚洲少妇诱惑| 亚洲欧美日韩国产一区二区三区| 欧美麻豆久久久久久中文| 91久久久久| 中文av一区二区| 国产精品高潮呻吟久久av无限| 日韩一二三区视频| 一本久道久久综合狠狠爱| 欧美日韩福利| 亚洲三级免费观看| 亚洲无人区一区| 国产精品日本欧美一区二区三区| 亚洲最新合集| 欧美一区二区精美| 国产精品日本| 欧美一区二区三区视频在线 | 免费观看成人鲁鲁鲁鲁鲁视频| 国产欧美一区二区三区在线看蜜臀| 欧美中文字幕不卡| 揄拍成人国产精品视频| 久色婷婷小香蕉久久| 亚洲欧洲日韩女同| 正在播放欧美视频| 国产人成精品一区二区三| 久久精品一级爱片| 亚洲精品日韩综合观看成人91| 亚洲综合电影一区二区三区| 国产日韩精品视频一区| 久久午夜激情| 亚洲最黄网站| 蜜桃av一区二区三区| 亚洲精品免费电影| 国产精品国产三级国产普通话蜜臀| 亚洲一区二区三区免费观看| 久久一区二区视频| 99成人在线| 国产亚洲一区二区在线观看| 麻豆成人综合网| 在线亚洲欧美专区二区| 久久五月激情| 亚洲一区999| 亚洲国产精品va在看黑人| 国产精品久久77777| 久久久久欧美精品| 夜久久久久久| 蜜臀va亚洲va欧美va天堂| 亚洲图片欧洲图片av| 在线不卡免费欧美| 国产精品自拍一区| 久久久亚洲欧洲日产国码αv | 精品动漫3d一区二区三区| 欧美日本一道本| 欧美在线观看视频在线| 99国产精品99久久久久久粉嫩 | 亚洲国产一区视频| 欧美日韩国产丝袜另类| 性欧美超级视频| 亚洲欧洲一区| 免费成人黄色片| 欧美一区二区在线播放| 一区二区三区高清不卡| 亚洲激情网站免费观看| 激情久久久久久| 国产欧美日韩综合一区在线播放 | 欧美高清成人| 狂野欧美一区|