天天看點

Linux下用C編寫WebSocet服務以響應HTML5的WebSocket請求

  • 在HTML5中新增了WebSocket,使得通訊變得更加友善。這樣一來,Web與硬體的互動除了CGI和XHR的方式外,又有了一個新的方式。那麼使用WebSocket又如何與下層通信呢?看看WebSocket的相關介紹就會發現,其類似于HTTP協定的通信,但又不同于HTTP協定通信,其最終使用的是TCP通信。具體的可以參照該文WebScoket 規範 + WebSocket 協定。

    我們先來看看通信的效果圖

    Linux下用C編寫WebSocet服務以響應HTML5的WebSocket請求
    Linux下用C編寫WebSocet服務以響應HTML5的WebSocket請求
    下面是實作的步驟

    1.建立SOCKET監聽

    WebSocket也是TCP通信,是以服務端需要先建立監聽,下面是實作的代碼。

    view source print ?

    01.

    02.

    #include <stdio.h>

    03.

    #include <stdlib.h>

    04.

    #include <string.h>

    05.

    #include <unistd.h>

    06.

    #include <sys socket.h=

    ""

    >

    07.

    #include <netinet in.h=

    ""

    >

    08.

    09.

    #include 

    "base64.h"

    10.

    #include 

    "sha1.h"

    11.

    #include 

    "intLib.h"

    12.

    13.

    14.

    #define REQUEST_LEN_MAX 

    1024

    15.

    #define DEFEULT_SERVER_PORT 

    8000

    16.

    #define WEB_SOCKET_KEY_LEN_MAX 

    256

    17.

    #define RESPONSE_HEADER_LEN_MAX 

    1024

    18.

    #define LINE_MAX 

    256

    19.

    20.

    21.

    void

    shakeHand(

    int

    connfd,

    const

    char

    *serverKey);

    22.

    char

    * fetchSecKey(

    const

    char

    * buf);

    23.

    char

    * computeAcceptKey(

    const

    char

    * buf);

    24.

    char

    * analyData(

    const

    char

    * buf,

    const

    int

    bufLen);

    25.

    char

    * packData(

    const

    char

    * message,unsigned 

    long

    * len);

    26.

    void

    response(

    const

    int

    connfd,

    const

    char

    * message);

    27.

    28.

    int

    main(

    int

    argc, 

    char

    *argv[])

    29.

    {

    30.

    struct sockaddr_in servaddr, cliaddr;

    31.

    socklen_t cliaddr_len;

    32.

    int

    listenfd, connfd;

    33.

    char

    buf[REQUEST_LEN_MAX];

    34.

    char

    *data;

    35.

    char

    str[INET_ADDRSTRLEN];

    36.

    char

    *secWebSocketKey;

    37.

    int

    i,n;

    38.

    int

    connected=

    ;

    //0:not connect.1:connected.

    39.

    int

    port= DEFEULT_SERVER_PORT;

    40.

    41.

    if

    (argc>

    1

    )

    42.

    {

    43.

    port=atoi(argv[

    1

    ]);

    44.

    }

    45.

    if

    (port<=

    ||port>

    0xFFFF

    )

    46.

    {

    47.

    printf("Port(%d) is out of range(

    1

    -%d)

    48.

    ",port,

    0xFFFF

    );

    49.

    return

    ;

    50.

    }

    51.

    listenfd = socket(AF_INET, SOCK_STREAM, 

    );

    52.

    53.

    bzero(&servaddr, sizeof(servaddr));

    54.

    servaddr.sin_family = AF_INET;

    55.

    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

    56.

    servaddr.sin_port = htons(port);

    57.

    58.

    bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

    59.

    60.

    listen(listenfd, 

    20

    );

    61.

    62.

    printf("Listen %d

    63.

    Accepting connections ...

    64.

    ",port);

    65.

    cliaddr_len = sizeof(cliaddr);

    66.

    connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);

    67.

    printf("From %s at PORT %d

    68.

    ",

    69.

    inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),

    70.

    ntohs(cliaddr.sin_port));

    71.

    72.

    while

    (

    1

    )

    73.

    {

    74.

    75.

    memset(buf,

    ,REQUEST_LEN_MAX);

    76.

    n = read(connfd, buf, REQUEST_LEN_MAX);

    77.

    printf("---------------------

    78.

    ");

    79.

    80.

    81.

    if

    (

    ==connected)

    82.

    {

    83.

    printf("read:%d

    84.

    %s

    85.

    ",n,buf);

    86.

    secWebSocketKey=computeAcceptKey(buf); 

    87.

    shakeHand(connfd,secWebSocketKey);

    88.

    connected=

    1

    ;

    89.

    continue

    ;

    90.

    }

    91.

    92.

    data=analyData(buf,n);

    93.

    response(connfd,data);

    94.

    }

    95.

    close(connfd);

    96.

    }</netinet></sys></unistd.h></string.h></stdlib.h></stdio.h>

    2.握手

    在建立監聽後,網頁向服務端發現WebSocket請求,這時需要先進行握手。握手時,用戶端會在協定中包含一個握手的唯一Key,服務端在拿到這個Key後,需要加入一個GUID,然後進行sha1的加密,再轉換成base64,最後再發回到用戶端。這樣就完成了一次握手。此種握手方式是針對chrome websocket 13的版本,其他版本的可能會有所不同。下面是實作的代碼。

    view source print ?

    001.

    char

    * fetchSecKey(

    const

    char

    * buf)

    002.

    {

    003.

    char

    *key;

    004.

    char

    *keyBegin;

    005.

    char

    *flag=

    "Sec-WebSocket-Key: "

    ;

    006.

    int

    i=

    , bufLen=

    ;

    007.

    008.

    key=(

    char

    *)malloc(WEB_SOCKET_KEY_LEN_MAX);

    009.

    memset(key,

    , WEB_SOCKET_KEY_LEN_MAX);

    010.

    if

    (!buf)

    011.

    {

    012.

    return

    NULL;

    013.

    }

    014.

    015.

    keyBegin=strstr(buf,flag);

    016.

    if

    (!keyBegin)

    017.

    {

    018.

    return

    NULL;

    019.

    }

    020.

    keyBegin+=strlen(flag);

    021.

    022.

    bufLen=strlen(buf);

    023.

    for

    (i=

    ;i<buflen;i++) 

    1.1

    =

    ""

    101

    =

    ""

    char

    =

    ""

    clientkey=

    "(char"

    const

    =

    ""

    guid=

    "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"

    http=

    ""

    i=

    ""

    int

    =

    ""

    n=

    ""

    pre=

    ""

    protocols=

    ""

    response=

    ""

    responseheader=

    ""

    return

    =

    ""

    s=

    ""

    sconnection:=

    ""

    serverkey=

    "base64_encode(sha1Data,"

    sha1data=

    "(char"

    sha1datatemp=

    "sha1_hash(clientKey);"

    short

    =

    ""

    ssec-websocket-accept:=

    ""

    supgrade:=

    ""

    switching=

    ""

    upgrade=

    ""

    void

    =

    ""

    websocket=

    ""

    >

    024.

    025.

    026.

    注意:<p> </p><p>

    1

    .Connection後面的值與HTTP通信時的不一樣了,是Upgrade,而Upgrade又對應到了websocket,這樣就辨別了該通信協定是websocket的方式。</p><p>

    2

    .在sha1加密後進行base64編碼時,使用sha1加密後的串必須将其當成

    16

    進制的字元串,将每兩個字元合成一個新的碼(

    -

    0xFF

    間)來進一步計算後,才可以進行base64換算(我開始時就在這裡折騰了很久,後面才弄明白還要加上這一步),如果是直接就base64,那就會握手失敗。</p><p>

    3

    .對于sha1和base64網上有很多,後面也附上我所使用的代碼。</p><h3>

    3

    .資料傳輸</h3><p>握手成功後就可以進行資料傳輸了,隻要按照WebSocket的協定來解就可以了。下面是實作的代碼</p><p> </p><pre 

    class

    =

    "brush:java;"

    >

    char

    * analyData(

    const

    char

    * buf,

    const

    int

    bufLen)

    027.

    {

    028.

    char

    * data;

    029.

    char

    fin, maskFlag,masks[

    4

    ];

    030.

    char

    * payloadData;

    031.

    char

    temp[

    8

    ];

    032.

    unsigned 

    long

    n, payloadLen=

    ;

    033.

    unsigned 

    short

    usLen=

    ;

    034.

    int

    i=

    ;

    035.

    036.

    037.

    if

    (bufLen < 

    2

    )

    038.

    {

    039.

    return

    NULL;

    040.

    }

    041.

    042.

    fin = (buf[

    ] & 

    0x80

    ) == 

    0x80

    // 1bit,1表示最後一幀 

    043.

    if

    (!fin)

    044.

    {

    045.

    return

    NULL;

    // 超過一幀暫不處理

    046.

    }

    047.

    048.

    maskFlag = (buf[

    1

    ] & 

    0x80

    ) == 

    0x80

    // 是否包含掩碼 

    049.

    if

    (!maskFlag)

    050.

    {

    051.

    return

    NULL;

    // 不包含掩碼的暫不處理

    052.

    }

    053.

    054.

    payloadLen = buf[

    1

    ] & 

    0x7F

    // 資料長度

    055.

    if

    (payloadLen == 

    126

    )

    056.

    {     

    057.

    memcpy(masks,buf+

    4

    4

    );     

    058.

    payloadLen =(buf[

    2

    ]&

    0xFF

    ) << 

    8

    | (buf[

    3

    ]&

    0xFF

    ); 

    059.

    payloadData=(

    char

    *)malloc(payloadLen);

    060.

    memset(payloadData,

    ,payloadLen);

    061.

    memcpy(payloadData,buf+

    8

    ,payloadLen);

    062.

    }

    063.

    else

    if

    (payloadLen == 

    127

    )

    064.

    {

    065.

    memcpy(masks,buf+

    10

    ,

    4

    ); 

    066.

    for

    ( i = 

    ; i < 

    8

    ; i++)

    067.

    {

    068.

    temp[i] = buf[

    9

    - i];

    069.

    }

    070.

    071.

    memcpy(&n,temp,

    8

    ); 

    072.

    payloadData=(

    char

    *)malloc(n);

    073.

    memset(payloadData,

    ,n);

    074.

    memcpy(payloadData,buf+

    14

    ,n);

    //toggle error(core dumped) if data is too long.

    075.

    payloadLen=n;   

    076.

    }

    077.

    else

    078.

    {  

    079.

    memcpy(masks,buf+

    2

    ,

    4

    );   

    080.

    payloadData=(

    char

    *)malloc(payloadLen);

    081.

    memset(payloadData,

    ,payloadLen);

    082.

    memcpy(payloadData,buf+

    6

    ,payloadLen);

    083.

    }

    084.

    085.

    for

    (i = 

    ; i < payloadLen; i++)

    086.

    {

    087.

    payloadData[i] = (

    char

    )(payloadData[i] ^ masks[i % 

    4

    ]);

    088.

    }

    089.

    090.

    printf("data(%d):%s

    091.

    ",payloadLen,payloadData);

    092.

    return

    payloadData;

    093.

    }

    094.

    095.

    char

    *  packData(

    const

    char

    * message,unsigned 

    long

    * len)

    096.

    {

    097.

    char

    * data=NULL;

    098.

    unsigned 

    long

    n;

    099.

    100.

    n=strlen(message);

    101.

    if

    (n < 

    126

    )

    102.

    {

    103.

    data=(

    char

    *)malloc(n+

    2

    );

    104.

    memset(data,

    ,n+

    2

    );   

    105.

    data[

    ] = 

    0x81

    ;

    106.

    data[

    1

    ] = n;

    107.

    memcpy(data+

    2

    ,message,n);

    108.

    *len=n+

    2

    ;

    109.

    }

    110.

    else

    if

    (n < 

    0xFFFF

    )

    111.

    {

    112.

    data=(

    char

    *)malloc(n+

    4

    );

    113.

    memset(data,

    ,n+

    4

    );

    114.

    data[

    ] = 

    0x81

    ;

    115.

    data[

    1

    ] = 

    126

    ;

    116.

    data[

    2

    ] = (n>>

    8

    0xFF

    );

    117.

    data[

    3

    ] = (n & 

    0xFF

    );

    118.

    memcpy(data+

    4

    ,message,n);   

    119.

    *len=n+

    4

    ;

    120.

    }

    121.

    else

    122.

    {

    123.

    124.

    // 暫不處理超長内容 

    125.

    *len=

    ;

    126.

    }

    127.

    128.

    129.

    return

    data;

    130.

    }

    131.

    132.

    void

    response(

    int

    connfd,

    const

    char

    * message)

    133.

    {

    134.

    char

    * data;

    135.

    unsigned 

    long

    n=

    ;

    136.

    int

    i;

    137.

    if

    (!connfd)

    138.

    {

    139.

    return

    ;

    140.

    }

    141.

    142.

    if

    (!data)

    143.

    {

    144.

    return

    ;

    145.

    }

    146.

    data=packData(message,&n);

    147.

    148.

    if

    (!data||n<=

    )

    149.

    {

    150.

    printf("data is empty!

    151.

    ");

    152.

    return

    ;

    153.

    }

    154.

    155.

    write(connfd,data,n);

    156.

    157.

    }</pre>

    158.

    <br>

    159.

    注意:

    160.

    <p> </p>

    161.

    <p>

    1

    .對于超過

    0xFFFF

    長度的資料在分析資料部分雖然作了處理,但是在memcpy時會報core dumped的錯誤,沒有解決,請過路的大牛幫忙指點。在packData部分也未對這一部分作處理。</p>

    162.

    <p>

    2

    .在這裡碰到了一個郁悶的問題,在命名函數時,将函數名寫的過長了(fetchSecWebSocketAcceptkey),結果導緻編譯通過,但在運作時卻莫名其妙的報core dumped的錯誤,試了很多方法才發現是這個原因,後将名字改短後就OK了。</p>

    163.

    <p>

    3

    .在回複資料時,隻要按websocket的協定進行回應就可以了。</p>

    164.

    <p>附上sha1、base64和intLib的代碼(sha1和base64是從網上摘來的)</p>

    165.

    <p>sha1.h</p>

    166.

    <p> </p>

    167.

    <pre 

    class

    =

    "brush:java;"

    >

    //sha1.h:對字元串進行sha1加密

    168.

    #ifndef _SHA1_H_

    169.

    #define _SHA1_H_

    170.

    171.

    #include <stdio.h>

    172.

    #include <stdlib.h>

    173.

    #include <string.h>

    174.

    175.

    176.

    typedef struct SHA1Context{

    177.

    unsigned Message_Digest[

    5

    ];     

    178.

    unsigned Length_Low;            

    179.

    unsigned Length_High;           

    180.

    unsigned 

    char

    Message_Block[

    64

    ];

    181.

    int

    Message_Block_Index;        

    182.

    int

    Computed;                   

    183.

    int

    Corrupted;                  

    184.

    } SHA1Context;

    185.

    186.

    void

    SHA1Reset(SHA1Context *);

    187.

    int

    SHA1Result(SHA1Context *);

    188.

    void

    SHA1Input( SHA1Context *,

    const

    char

    *,unsigned);

    189.

    #endif

    190.

    191.

    192.

    #define SHA1CircularShift(bits,<a href=

    "http://www.it165.net/edu/ebg/"

    target=

    "_blank"

    class

    =

    "keylink"

    >word</a>) ((((<a href=

    "http://www.it165.net/edu/ebg/"

    target=

    "_blank"

    class

    =

    "keylink"

    >word</a>) << (bits)) & 

    0xFFFFFFFF

    ) | ((word) >> (

    32

    -(bits))))

    193.

    194.

    void

    SHA1ProcessMessageBlock(SHA1Context *);

    195.

    void

    SHA1PadMessage(SHA1Context *);

    196.

    197.

    void

    SHA1Reset(SHA1Context *context){

    // 初始化動作

    198.

    context->Length_Low             = 

    ;

    199.

    context->Length_High            = 

    ;

    200.

    context->Message_Block_Index    = 

    ;

    201.

    202.

    context->Message_Digest[

    ]      = 

    0x67452301

    ;

    203.

    context->Message_Digest[

    1

    ]      = 

    0xEFCDAB89

    ;

    204.

    context->Message_Digest[

    2

    ]      = 

    0x98BADCFE

    ;

    205.

    context->Message_Digest[

    3

    ]      = 

    0x10325476

    ;

    206.

    context->Message_Digest[

    4

    ]      = 

    0xC3D2E1F0

    ;

    207.

    208.

    context->Computed   = 

    ;

    209.

    context->Corrupted  = 

    ;

    210.

    }

    211.

    212.

    213.

    int

    SHA1Result(SHA1Context *context){

    // 成功傳回1,失敗傳回0

    214.

    if

    (context->Corrupted) {

    215.

    return

    ;

    216.

    }

    217.

    if

    (!context->Computed) {

    218.

    SHA1PadMessage(context);

    219.

    context->Computed = 

    1

    ;

    220.

    }

    221.

    return

    1

    ;

    222.

    }

    223.

    224.

    225.

    void

    SHA1Input(SHA1Context *context,

    const

    char

    *message_array,unsigned length){

    226.

    if

    (!length) 

    return

    ;

    227.

    228.

    if

    (context->Computed || context->Corrupted){

    229.

    context->Corrupted = 

    1

    ;

    230.

    return

    ;

    231.

    }

    232.

    233.

    while

    (length-- && !context->Corrupted){

    234.

    context->Message_Block[context->Message_Block_Index++] = (*message_array & 

    0xFF

    );

    235.

    236.

    context->Length_Low += 

    8

    ;

    237.

    238.

    context->Length_Low &= 

    0xFFFFFFFF

    ;

    239.

    if

    (context->Length_Low == 

    ){

    240.

    context->Length_High++;

    241.

    context->Length_High &= 

    0xFFFFFFFF

    ;

    242.

    if

    (context->Length_High == 

    ) context->Corrupted = 

    1

    ;

    243.

    }

    244.

    245.

    if

    (context->Message_Block_Index == 

    64

    ){

    246.

    SHA1ProcessMessageBlock(context);

    247.

    }

    248.

    message_array++;

    249.

    }

    250.

    }

    251.

    252.

    void

    SHA1ProcessMessageBlock(SHA1Context *context){

    253.

    const

    unsigned K[] = {

    0x5A827999

    0x6ED9EBA1

    0x8F1BBCDC

    0xCA62C1D6

    };

    254.

    int

    t;               

    255.

    unsigned    temp;            

    256.

    unsigned    W[

    80

    ];           

    257.

    unsigned    A, B, C, D, E;   

    258.

    259.

    for

    (t = 

    ; t < 

    16

    ; t++) {

    260.

    W[t] = ((unsigned) context->Message_Block[t * 

    4

    ]) << 

    24

    ;

    261.

    W[t] |= ((unsigned) context->Message_Block[t * 

    4

    1

    ]) << 

    16

    ;

    262.

    W[t] |= ((unsigned) context->Message_Block[t * 

    4

    2

    ]) << 

    8

    ;

    263.

    W[t] |= ((unsigned) context->Message_Block[t * 

    4

    3

    ]);

    264.

    }

    265.

    266.

    for

    (t = 

    16

    ; t < 

    80

    ; t++)  W[t] = SHA1CircularShift(

    1

    ,W[t-

    3

    ] ^ W[t-

    8

    ] ^ W[t-

    14

    ] ^ W[t-

    16

    ]);

    267.

    268.

    A = context->Message_Digest[

    ];

    269.

    B = context->Message_Digest[

    1

    ];

    270.

    C = context->Message_Digest[

    2

    ];

    271.

    D = context->Message_Digest[

    3

    ];

    272.

    E = context->Message_Digest[

    4

    ];

    273.

    274.

    for

    (t = 

    ; t < 

    20

    ; t++) {

    275.

    temp =  SHA1CircularShift(

    5

    ,A) + ((B & C) | ((~B) & D)) + E + W[t] + K[

    ];

    276.

    temp &= 

    0xFFFFFFFF

    ;

    277.

    E = D;

    278.

    D = C;

    279.

    C = SHA1CircularShift(

    30

    ,B);

    280.

    B = A;

    281.

    A = temp;

    282.

    }

    283.

    for

    (t = 

    20

    ; t < 

    40

    ; t++) {

    284.

    temp = SHA1CircularShift(

    5

    ,A) + (B ^ C ^ D) + E + W[t] + K[

    1

    ];

    285.

    temp &= 

    0xFFFFFFFF

    ;

    286.

    E = D;

    287.

    D = C;

    288.

    C = SHA1CircularShift(

    30

    ,B);

    289.

    B = A;

    290.

    A = temp;

    291.

    }

    292.

    for

    (t = 

    40

    ; t < 

    60

    ; t++) {

    293.

    temp = SHA1CircularShift(

    5

    ,A) + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[

    2

    ];

    294.

    temp &= 

    0xFFFFFFFF

    ;

    295.

    E = D;

    296.

    D = C;

    297.

    C = SHA1CircularShift(

    30

    ,B);

    298.

    B = A;

    299.

    A = temp;

    300.

    }

    301.

    for

    (t = 

    60

    ; t < 

    80

    ; t++) {

    302.

    temp = SHA1CircularShift(

    5

    ,A) + (B ^ C ^ D) + E + W[t] + K[

    3

    ];

    303.

    temp &= 

    0xFFFFFFFF

    ;

    304.

    E = D;

    305.

    D = C;

    306.

    C = SHA1CircularShift(

    30

    ,B);

    307.

    B = A;

    308.

    A = temp;

    309.

    }

    310.

    context->Message_Digest[

    ] = (context->Message_Digest[

    ] + A) & 

    0xFFFFFFFF

    ;

    311.

    context->Message_Digest[

    1

    ] = (context->Message_Digest[

    1

    ] + B) & 

    0xFFFFFFFF

    ;

    312.

    context->Message_Digest[

    2

    ] = (context->Message_Digest[

    2

    ] + C) & 

    0xFFFFFFFF

    ;

    313.

    context->Message_Digest[

    3

    ] = (context->Message_Digest[

    3

    ] + D) & 

    0xFFFFFFFF

    ;

    314.

    context->Message_Digest[

    4

    ] = (context->Message_Digest[

    4

    ] + E) & 

    0xFFFFFFFF

    ;

    315.

    context->Message_Block_Index = 

    ;

    316.

    }

    317.

    318.

    void

    SHA1PadMessage(SHA1Context *context){

    319.

    if

    (context->Message_Block_Index > 

    55

    ) {

    320.

    context->Message_Block[context->Message_Block_Index++] = 

    0x80

    ;

    321.

    while

    (context->Message_Block_Index < 

    64

    )  context->Message_Block[context->Message_Block_Index++] = 

    ;

    322.

    SHA1ProcessMessageBlock(context);

    323.

    while

    (context->Message_Block_Index < 

    56

    ) context->Message_Block[context->Message_Block_Index++] = 

    ;

    324.

    else

    {

    325.

    context->Message_Block[context->Message_Block_Index++] = 

    0x80

    ;

    326.

    while

    (context->Message_Block_Index < 

    56

    ) context->Message_Block[context->Message_Block_Index++] = 

    ;

    327.

    }

    328.

    context->Message_Block[

    56

    ] = (context->Length_High >> 

    24

    ) & 

    0xFF

    ;

    329.

    context->Message_Block[

    57

    ] = (context->Length_High >> 

    16

    ) & 

    0xFF

    ;

    330.

    context->Message_Block[

    58

    ] = (context->Length_High >> 

    8

    ) & 

    0xFF

    ;

    331.

    context->Message_Block[

    59

    ] = (context->Length_High) & 

    0xFF

    ;

    332.

    context->Message_Block[

    60

    ] = (context->Length_Low >> 

    24

    ) & 

    0xFF

    ;

    333.

    context->Message_Block[

    61

    ] = (context->Length_Low >> 

    16

    ) & 

    0xFF

    ;

    334.

    context->Message_Block[

    62

    ] = (context->Length_Low >> 

    8

    ) & 

    0xFF

    ;

    335.

    context->Message_Block[

    63

    ] = (context->Length_Low) & 

    0xFF

    ;

    336.

    337.

    SHA1ProcessMessageBlock(context);

    338.

    }

    339.

    340.

    361.

    362.

    char

    * sha1_hash(

    const

    char

    *source){

    // Main

    363.

    SHA1Context sha;

    364.

    char

    *buf;

    //[128];

    365.

    366.

    SHA1Reset(&sha);

    367.

    SHA1Input(&sha, source, strlen(source));

    368.

    369.

    if

    (!SHA1Result(&sha)){

    370.

    printf(

    "SHA1 ERROR: Could not compute message digest"

    );

    371.

    return

    NULL;

    372.

    else

    {

    373.

    buf=(

    char

    *)malloc(

    128

    );

    374.

    memset(buf,

    ,sizeof(buf));

    375.

    sprintf(buf, 

    "%08X%08X%08X%08X%08X"

    , sha.Message_Digest[

    ],sha.Message_Digest[

    1

    ],

    376.

    sha.Message_Digest[

    2

    ],sha.Message_Digest[

    3

    ],sha.Message_Digest[

    4

    ]);

    377.

    //lr_save_string(buf, lrvar);

    378.

    379.

    //return strlen(buf);

    380.

    return

    buf;

    381.

    }

    382.

    }

    383.

    </string.h></stdlib.h></stdio.h></pre>

    384.

    <br>

    385.

    base64.h

    386.

    <p> </p>

    387.

    <p> </p>

    388.

    <pre 

    class

    =

    "brush:java;"

    >#ifndef _BASE64_H_

    389.

    #define _BASE64_H_

    390.

    391.

    #include <stdio.h>

    392.

    #include <stdlib.h>

    393.

    #include <string.h>

    394.

    395.

    const

    char

    base[] = 

    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="

    ;

    396.

    char

    * base64_encode(

    const

    char

    * data, 

    int

    data_len);

    397.

    char

    *base64_decode(

    const

    char

    * data, 

    int

    data_len);

    398.

    static

    char

    find_pos(

    char

    ch);

    399.

    400.

    401.

    char

    *base64_encode(

    const

    char

    * data, 

    int

    data_len)

    402.

    {

    403.

    //int data_len = strlen(data);

    404.

    int

    prepare = 

    ;

    405.

    int

    ret_len;

    406.

    int

    temp = 

    ;

    407.

    char

    *ret = NULL;

    408.

    char

    *f = NULL;

    409.

    int

    tmp = 

    ;

    410.

    char

    changed[

    4

    ];

    411.

    int

    i = 

    ;

    412.

    ret_len = data_len / 

    3

    ;

    413.

    temp = data_len % 

    3

    ;

    414.

    if

    (temp > 

    )

    415.

    {

    416.

    ret_len += 

    1

    ;

    417.

    }

    418.

    ret_len = ret_len*

    4

    1

    ;

    419.

    ret = (

    char

    *)malloc(ret_len);

    420.

    421.

    if

    ( ret == NULL)

    422.

    {

    423.

    printf("No enough memory.

    424.

    ");

    425.

    exit(

    );

    426.

    }

    427.

    memset(ret, 

    , ret_len);

    428.

    f = ret;

    429.

    while

    (tmp < data_len)

    430.

    {

    431.

    temp = 

    ;

    432.

    prepare = 

    ;

    433.

    memset(changed, 

    ''

    4

    );

    434.

    while

    (temp < 

    3

    )

    435.

    {

    436.

    //printf("tmp = %d

    437.

    ", tmp);

    438.

    if

    (tmp >= data_len)

    439.

    {

    440.

    break

    ;

    441.

    }

    442.

    prepare = ((prepare << 

    8

    ) | (data[tmp] & 

    0xFF

    ));

    443.

    tmp++;

    444.

    temp++;

    445.

    }

    446.

    prepare = (prepare<<((

    3

    -temp)*

    8

    ));

    447.

    //printf("before for : temp = %d, prepare = %d

    448.

    ", temp, prepare);

    449.

    for

    (i = 

    ; i < 

    4

    ;i++ )

    450.

    {

    451.

    if

    (temp < i)

    452.

    {

    453.

    changed[i] = 

    0x40

    ;

    454.

    }

    455.

    else

    456.

    {

    457.

    changed[i] = (prepare>>((

    3

    -i)*

    6

    )) & 

    0x3F

    ;

    458.

    }

    459.

    *f = base[changed[i]];

    460.

    //printf("%.2X", changed[i]);

    461.

    f++;

    462.

    }

    463.

    }

    464.

    *f = 

    ''

    ;

    465.

    466.

    return

    ret;

    467.

    468.

    }

    469.

    470.

    static

    char

    find_pos(

    char

    ch)  

    471.

    {

    472.

    char

    *ptr = (

    char

    *)strrchr(base, ch);

    //the last position (the only) in base[]

    473.

    return

    (ptr - base);

    474.

    }

    475.

    476.

    char

    *base64_decode(

    const

    char

    *data, 

    int

    data_len)

    477.

    {

    478.

    int

    ret_len = (data_len / 

    4

    ) * 

    3

    ;

    479.

    int

    equal_count = 

    ;

    480.

    char

    *ret = NULL;

    481.

    char

    *f = NULL;

    482.

    int

    tmp = 

    ;

    483.

    int

    temp = 

    ;

    484.

    char

    need[

    3

    ];

    485.

    int

    prepare = 

    ;

    486.

    int

    i = 

    ;

    487.

    if

    (*(data + data_len - 

    1

    ) == 

    '='

    )

    488.

    {

    489.

    equal_count += 

    1

    ;

    490.

    }

    491.

    if

    (*(data + data_len - 

    2

    ) == 

    '='

    )

    492.

    {

    493.

    equal_count += 

    1

    ;

    494.

    }

    495.

    if

    (*(data + data_len - 

    3

    ) == 

    '='

    )

    496.

    {

    //seems impossible

    497.

    equal_count += 

    1

    ;

    498.

    }

    499.

    switch

    (equal_count)

    500.

    {

    501.

    case

    :

    502.

    ret_len += 

    4

    ;

    //3 + 1 [1 for NULL]

    503.

    break

    ;

    504.

    case

    1

    :

    505.

    ret_len += 

    4

    ;

    //Ceil((6*3)/8)+1

    506.

    break

    ;

    507.

    case

    2

    :

    508.

    ret_len += 

    3

    ;

    //Ceil((6*2)/8)+1

    509.

    break

    ;

    510.

    case

    3

    :

    511.

    ret_len += 

    2

    ;

    //Ceil((6*1)/8)+1

    512.

    break

    ;

    513.

    }

    514.

    ret = (

    char

    *)malloc(ret_len);

    515.

    if

    (ret == NULL)

    516.

    {

    517.

    printf("No enough memory.

    518.

    ");

    519.

    exit(

    );

    520.

    }

    521.

    memset(ret, 

    , ret_len);

    522.

    f = ret;

    523.

    while

    (tmp < (data_len - equal_count))

    524.

    {

    525.

    temp = 

    ;

    526.

    prepare = 

    ;

    527.

    memset(need, 

    4

    );

    528.

    while

    (temp < 

    4

    )

    529.

    {

    530.

    if

    (tmp >= (data_len - equal_count))

    531.

    {

    532.

    break

    ;

    533.

    }

    534.

    prepare = (prepare << 

    6

    ) | (find_pos(data[tmp]));

    535.

    temp++;

    536.

    tmp++;

    537.

    }

    538.

    prepare = prepare << ((

    4

    -temp) * 

    6

    );

    539.

    for

    (i=

    ; i<

    3

    ;i++ )

    540.

    {

    541.

    if

    (i == temp)

    542.

    {

    543.

    break

    ;

    544.

    }

    545.

    *f = (

    char

    )((prepare>>((

    2

    -i)*

    8

    )) & 

    0xFF

    );

    546.

    f++;

    547.

    }

    548.

    }

    549.

    *f = 

    ''

    ;

    550.

    return

    ret;

    551.

    }

    552.

    553.

    #endif

    554.

    </string.h></stdlib.h></stdio.h></pre>

    555.

    <br>

    556.

    intLib.h

    557.

    <p> </p>

    558.

    <p> </p>

    559.

    <pre 

    class

    =

    "brush:java;"

    >#ifndef _INT_LIB_H_

    560.

    #define _INT_LIB_H_

    561.

    int

    tolower(

    int

    c)

    562.

    {

    563.

    if

    (c >= 

    'A'

    && c <= 

    'Z'

    )

    564.

    {

    565.

    return

    c + 

    'a'

    'A'

    ;

    566.

    }

    567.

    else

    568.

    {

    569.

    return

    c;

    570.

    }

    571.

    }

    572.

    573.

    int

    htoi(

    const

    char

    s[],

    int

    start,

    int

    len)

    574.

    {

    575.

    int

    i,j;

    576.

    int

    n = 

    ;

    577.

    if

    (s[

    ] == 

    '0'

    && (s[

    1

    ]==

    'x'

    || s[

    1

    ]==

    'X'

    )) 

    //判斷是否有前導0x或者0X

    578.

    {

    579.

    i = 

    2

    ;

    580.

    }

    581.

    else

    582.

    {

    583.

    i = 

    ;

    584.

    }

    585.

    i+=start;

    586.

    j=

    ;

    587.

    for

    (; (s[i] >= 

    '0'

    && s[i] <= 

    '9'

    )

    588.

    || (s[i] >= 

    'a'

    && s[i] <= 

    'f'

    ) || (s[i] >=

    'A'

    && s[i] <= 

    'F'

    );++i)

    589.

    {  

    590.

    if

    (j>=len)

    591.

    {

    592.

    break

    ;

    593.

    }

    594.

    if

    (tolower(s[i]) > 

    '9'

    )

    595.

    {

    596.

    n = 

    16

    * n + (

    10

    + tolower(s[i]) - 

    'a'

    );

    597.

    }

    598.

    else

    599.

    {

    600.

    n = 

    16

    * n + (tolower(s[i]) - 

    '0'

    );

    601.

    }

    602.

    j++;

    603.

    }

    604.

    return

    n;

    605.

    }

    606.

    607.

    608.

    #endif

    609.

    </pre>

    610.

    <br>

    611.

    出處http:

    //blog.csdn.net/xxdddail/article/details/19070149

    612.

    <p> </p>

    613.

    </buflen;i++)>