openssl之BIO系列之18---接受(accept)類型BIO,openssl18---

來源:互聯網
上載者:User

openssl之BIO系列之18---接受(accept)類型BIO,openssl18---

接受(accept)類型BIO

    ---根據openssl doc\crypto\bio_s_accept.pod翻譯和自己的理解寫成

    (作者:DragonKing, Mail: wzhah@263.net ,發佈於:http://gdwzh.126.com之o

penssl專業論壇)

    接受(accept)類型的BIO跟串連(connect)類型BIO是相對應的,它封裝了Socke

t的accept方法及其相關的一些操作,使得能夠對不同的平台使用同一的函數進行操作。

其定義的相關函數如下(openssl\bio.h):

     BIO_METHOD * BIO_s_accept(void);

     #define BIO_set_accept_port(b,name) BIO_ctrl(b,BIO_C_SET_ACCEPT,0,(char

 *)name)

     #define BIO_get_accept_port(b) BIO_ptr_ctrl(b,BIO_C_GET_ACCEPT,0)

     BIO *BIO_new_accept(char *host_port);

     #define BIO_set_nbio_accept(b,n) BIO_ctrl(b,BIO_C_SET_ACCEPT,1,(n)?"a":

NULL)

     #define BIO_set_accept_bios(b,bio) BIO_ctrl(b,BIO_C_SET_ACCEPT,2,(char 

*)bio)

     #define BIO_set_bind_mode(b,mode) BIO_ctrl(b,BIO_C_SET_BIND_MODE,mode,N

ULL)

     #define BIO_get_bind_mode(b,mode) BIO_ctrl(b,BIO_C_GET_BIND_MODE,0,NULL

)

     #define BIO_BIND_NORMAL 0

     #define BIO_BIND_REUSEADDR_IF_UNUSED 1

     #define BIO_BIND_REUSEADDR 2

     #define BIO_do_accept(b) BIO_do_handshake(b)

    【BIO_s_accept】

    該函數返回一個接受(Accept)類型的BIO_METHOD結構,其定義如下:

    static BIO_METHOD methods_acceptp=

     {

     BIO_TYPE_ACCEPT,

     "socket accept",

     acpt_write,

     acpt_read,

     acpt_puts,

     NULL, /* connect_gets, */

     acpt_ctrl,

     acpt_new,

     acpt_free,

     NULL,

     };

    通過該結構我們可以一目瞭然的知道該方法支援什麼I/O操作,在本類型中,BIO_g

ets的操作是不支援的。跟串連(connect)類型BIO一樣,openssl也定義了一個維護接

受Socket資訊的結構,在此我也不再詳細介紹該結構,大家參考bss_acpt.c檔案。

    本類型的BIO對各種平台的TCP/IP的accept做了封裝,所以在使用的時候就可以同一

的使用BIO的規則進行操作,而不用擔心因為不同的平台帶來程式改寫或增加移植的工作

量,這也是BIO很重要的一個目的。

    BIO_read和BIO_write函數操作調用了底層平台串連的I/O相關操作,如果這時候沒

有串連建立,連接埠設定正確,那麼該BIO就會等待串連的建立。事實上,當一個串連建立

的時候,一個新的socket類型BIO就會被建立並附加到BIO鏈中,形成accept->socket的

BIO結構,所以這時候對初始化了的接受socket進行IO操作就會導致它處於等待串連建立

的狀態。當一個接受類型的BIO在BIO鏈的末尾的時候,在處理I/O調用之前它會先等待一

個串連的建立;如果不是在末尾,那麼它簡單的把I/O調用傳到下一個BIO。

    如果接受(accept)類型BIO的關閉標誌設定了,那麼當BIO被釋放的時候,該BIO鏈

上任何活動的串連和socket都會被關閉。

    BIO_get_fd和BIO_set_fd可以用來取得和設定該串連的socket描述符,詳細情況參

看《BIO系列之12---描述符(fd)類型BIO》。

    【BIO_set_accept_port】

    該函數使用字串名來設定接受連接埠。其形式為“host:port”,“host”是要使用的

介面,“port”是連接埠。這兩部分都可以為“*”,這時候表示可以使用任意介面和連接埠

。這裡的連接埠的字串含義跟串連(connect)類型BIO裡面定義的一樣,可以為數字形

式的,可以使用getservbyname函數去匹配得到,還可以使用字串的表,請參看串連型

BIO說明的相關部分。

    【BIO_new_accept】

    該函數將BIO_new和BIO_set_accept_port函數放在一個函數裡面調用,建立一個新

的接受(accept)類型的BIO。

    【BIO_set_nbio_accept】

    該函數設定接受socket是否為阻塞模式(預設),如果參數n為0,為阻塞模式,n為

1則為非阻塞模式。

    【BIO_set_accept_bios】

    該函數用來設定一個BIO鏈,當接受到一個串連的時候,這個設定好的BIO鏈就會被

複製或附加到整個BIO鏈上來。有的時候這中處理方法是非常好的,比如,如果每個串連

都需要一個緩衝區或SSL類型的BIO,這時候使用本函數就省了很多麻煩了。需要注意的

是,在調用本函數後,這個設定的鏈上的BIO不能自己釋放,在接受(accept)BIO被釋

放後,它們會自動釋放。

    當該函數調用的時候,其設定的BIO鏈位於接受BIO和socket類型的BIO之間,即形成

:accept->otherbios->socket的新的BIO鏈。

    【BIO_set_bind_mode和BIO_get_bind_mode】

    這兩個函數用來設定和取得目前的繫結模式。如果設定為BIO_BIND_NORMAL(預設)

,那麼另外一個socket就不能綁定到同一個連接埠。如果設定為BIO_BIND_REUSEADDR ,那

麼另外的socket可以綁定到同一個連接埠。如果設定為BIO_BIND_REUSEADDR_IF_UNUSED,

那麼首先會嘗試以BIO_BIND_NORMAL的模式綁定到連接埠,如果失敗了而且連接埠沒有使用,

那麼就會使用BIO_BIND_REUSEADDR 模式綁定到連接埠。

    【BIO_do_accept】

    該函數有兩個功能,當它在接受(accept)BIO設定好之後第一被調用的時候,它會

建立一個接受socket並把它跟地址綁定;第二次被調用的時候,它會等待串連的到來。

 

    【注意】

    如果伺服器端希望可以處理多個串連的情況(通常都是這樣的),那麼接受BIO必須

能夠用來處理以後的串連,這時候可以這樣做:

    等待到一個串連後,調用

     connection=BIO_pop(accept)

    這樣,cnnection會包含一個最近建立的串連的BIO,accept就再次成為一個獨立的

BIO,可以用來處理其它串連了。如果沒有其它串連建立,那麼就可以使用BIO_free釋放

該BIO。

    當然,如果只有一個串連需要處理,也可以使用串連BIO本身來進行I/O操作。但是

一般來說不推薦這樣做,因為這時候該接受BIO依然處於接受其它串連建立的狀態。這可

以使用上述的方法解決。

    【例子】

    這個例子在4444連接埠接受了兩個串連,發送資訊到每個串連上然後釋放他們。

     BIO *abio, *cbio, *cbio2;

     ERR_load_crypto_strings();

     abio = BIO_new_accept("4444");

     /* 首先調用BIO_accept啟動接受BIO */

     if(BIO_do_accept(abio) <= 0) {

     fprintf(stderr, "Error setting up accept\n");

     ERR_print_errors_fp(stderr);

     exit(0);

     }

     /* 等待串連建立*/

     if(BIO_do_accept(abio) <= 0) {

     fprintf(stderr, "Error accepting connection\n");

     ERR_print_errors_fp(stderr);

     exit(0);

     }

     fprintf(stderr, "Connection 1 established\n");

     /* 返回串連的BIO*/

     cbio = BIO_pop(abio);

     BIO_puts(cbio, "Connection 1: Sending out Data on initial connection\n"

);

     fprintf(stderr, "Sent out data on connection 1\n");

     /* 等待另一個串連的建立 */

     if(BIO_do_accept(abio) <= 0) {

     fprintf(stderr, "Error accepting connection\n");

     ERR_print_errors_fp(stderr);

     exit(0);

     }

     fprintf(stderr, "Connection 2 established\n");

     /* 關閉串連BIO,不再接受串連的建立 */

     cbio2 = BIO_pop(abio);

     BIO_free(abio);

     BIO_puts(cbio2, "Connection 2: Sending out Data on second\n");

     fprintf(stderr, "Sent out data on connection 2\n");

     BIO_puts(cbio, "Connection 1: Second connection established\n");

     /* 關閉這兩個串連 */

     BIO_free(cbio);

     BIO_free(cbio2);

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.