c++websocketサービス側とJavaScript通信を実現

22392 ワード

c++websocketサービス側とJavaScript通信を実現
次の点に注意してください.
  • まずwebsocketとは何かを理解し、ここでは
  • について説明しない.
  • websocketのインタラクティブプロトコル
  • を明確にする
    目次[TOC]を使用してディレクトリを生成します.
  • c websocketサービス側とJavaScript通信を実現
  • ディレクトリ
  • 握手プロトコルとプロトコルの解析
  • まず普通のsocket
  • を建てに来ました
  • 二握手プロトコル
  • 3ワークスレッドクライアント応答情報を処理するバイトコード
  • 4最後に応答クライアント
  • 5最後に応答クライアント


  • 握手プロトコルとプロトコルの解析
    多くの資料にwebsocketの握手プロトコルが詳しく紹介されていますが、ここではあまり言わないで、直接コードをつけましょう.
    一、まず普通のsocketを建てる
    void Initsocket(){
        WORD imgrequest;
        WSADATA wsadata;
        imgrequest = MAKEWORD(1, 1);
        int err;
        err = WSAStartup(imgrequest, &wsadata);
        if (!err){
            printf("      
    "
    ); }else{ printf("
    "
    ); return; } SOCKET sersocket = socket(AF_INET, SOCK_STREAM, 0); SOCKADDR_IN addr; addr.sin_family = AF_INET; addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //ip addr.sin_port = htons(8899); // bind(sersocket, (SOCKADDR*)&addr, sizeof(SOCKADDR));// listen(sersocket, 10); // SOCKADDR_IN clientsocket; int len = sizeof(SOCKADDR); boolean isConnected = false; int i = 0; while (true){ SOCKET serConn = accept(sersocket, (SOCKADDR*)&clientsocket, &len); printf("
    "
    ); // HANDLE hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)WorkThread, (LPVOID)serConn, 0, 0); if (hThread1 != NULL) { CloseHandle(hThread1); } Sleep(1000); closesocket(serConn); } }

    二、握手協議
    /*  key   */
    void requestInfo(SOCKET sockClient, char * request){
        char recev[1024] = "";
        recv(sockClient, recev, 2048, 0);
        //cout << recev << endl;
        string s = recev;
        int i = s.find("Sec-WebSocket-Key");
        s = s.substr(i + 19, 24);
        //               key,  key            
        //                
        getKey(request,s);
    }
    /*  
                key    sha  ,             
    */
    void getKey(char *request, string clientkey){
        strcat(request, "HTTP/1.1 101 Switching Protocols\r
    "
    ); strcat(request, "Connection: upgrade\r
    "
    ); strcat(request, "Sec-WebSocket-Accept: "); string server_key = clientkey; server_key += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; SHA1 sha; unsigned int message_digest[5]; cout <<"server_key:"<< server_key << endl; sha.Reset(); sha << server_key.c_str(); sha.Result(message_digest); for (int i = 0; i < 5; i++) { message_digest[i] = htonl(message_digest[i]); } server_key = base64_encode(reinterpret_cast<const unsigned char*>(message_digest), 20); server_key += "\r
    "
    ; strcat(request, server_key.c_str()); strcat(request, "Upgrade: websocket\r
    \r
    "
    ); cout << "shalserver_key:" << server_key << endl; }

    三、作業スレッドはクライアント応答情報のバイトコードを処理する
    /*    */
    void WorkThread(SOCKET sockClient){
        char request[1024] = "";  //    
        char clieninfo[2048]= ""; //       
        int len = 0;              //     
        int point = 0;            //      
        int tmppoint = 0;         //      
    
        //    
        requestInfo(sockClient, request);
        respondInfo(sockClient, request);
        //       
        //       ,            ,        
        //      ,              
        //         
        len=recv(sockClient, clieninfo, 2048, 0);
        string ss = clieninfo;
        cout << "    
    :"
    <" :"<< ss << endl; if (len>0){ /* b , point , , */ byte b[4096] = ""; // memcpy(b, clieninfo, 2048); cout << " :" << b << endl; for (int i = 0; i <= 33; i++){ printf("%d\t", b[i]); } printf("
    "
    ); // int first = b[point] & 0xFF; printf(" :%d,%d,%d
    "
    , point, b[point], first); byte opCode = (byte)(first & 0x0F); //0000 1111 opCode 00001111 if (opCode == 8){ closesocket(sockClient); } // first = b[++point]; // int payloadLength = first & 0x7F; printf(" :%d,[%d],%d
    "
    , point, b[point], payloadLength); if (payloadLength == 126) { byte extended[2] = ""; extended[0] = b[++point]; extended[1] = b[++point]; int shift = 0; payloadLength = 0; for (int i = 2- 1; i >= 0; i--) { payloadLength = payloadLength + ((extended[i] & 0xFF) << shift); shift += 8; } }else if (payloadLength == 127) { byte extended[8] = ""; tmppoint = ++point; // point = --point; for (int i = 0; i < 8;i++){ extended[i] = b[tmppoint + i]; point++; } int shift = 0; payloadLength = 0; for (int i = 8 - 1; i >= 0; i--) { payloadLength = payloadLength + ((extended[i] & 0xFF) << shift); shift += 8; } } // 126 127 if ((payloadLength != 126) || (payloadLength != 127)){ point = 1; } cout << " :" << payloadLength << endl; // , byte mask[4] = ""; tmppoint = ++point; // , point = --point; // for (int i = 0; i < 4; i++){ mask[i] = b[tmppoint + i]; point++; printf(" mask :%d,[%d],%d\t
    "
    , point, mask[i], payloadLength); } byte changeb[4096] = ""; // , int length = payloadLength; int readThisFragment = 1; // while (payloadLength > 0){ int maskbyte = b[++point]; int index = (readThisFragment - 1) % 4; maskbyte = maskbyte ^ (mask[index] & 0xFF); changeb[readThisFragment-1] = (byte)maskbyte; printf(" :%d,[%d],%d
    "
    , point, maskbyte, readThisFragment); payloadLength--; readThisFragment++; } char a[4096] = "1231"; byte test[1024] = ""; memcpy(test, a, strlen(a)); Sleep(5000);// // //respondClient(sockClient, changeb, length, true); respondClient(sockClient, test, strlen(a), true); // char charb[4096] = ""; memcpy(charb, changeb, length); //charb[length] = 0; for (int i = 0; i < length;i++){ printf("%d\t", charb[i]); } printf("%d
    "
    ); string s = charb; cout << " :" << s << endl; //closesocket(sockClient); } } /* */ void respondInfo(SOCKET sockClient, char * request){ send(sockClient, request, strlen(request), 0); }

    四、最後にクライアントに応答する
    /* */
    void respondClient(SOCKET sockClient, byte charb[],int length, boolean finalFragment){
        byte buf[1024] = "";
        int first = 0x00;
        int tmp = 0;
        if (finalFragment) {
            first = first + 0x80;
            first = first + 0x1;
        }
        buf[0] = first;
        tmp = 1;
        cout <<"    :"<< length << endl;
        unsigned int nuNum = (unsigned)length;
        if (length < 126) {
            buf[1] = length;
            tmp = 2;
        }else if (length < 65536) {
            buf[1] = 126;
            buf[2] = nuNum >> 8;
            buf[3] = length & 0xFF;
            tmp = 4;
        }else {
            //      65536
            buf[1] = 127;
            buf[2] = 0;
            buf[3] = 0;
            buf[4] = 0;
            buf[5] = 0;
            buf[6] = nuNum >> 24;
            buf[7] = nuNum >> 16;
            buf[8] = nuNum >> 8;
            buf[9] = nuNum & 0xFF;
            tmp = 10;
        }
        for (int i = 0; i < length;i++){
            buf[tmp+i]= charb[i];
            printf("        :%d
    "
    , charb[i]); } char charbuf[1024] = ""; memcpy(charbuf, buf, length + tmp); send(sockClient, charbuf, 1024, 0); }

    五、最後にクライアントに応答する
    非常に簡単なテストコード
    (function(){
        var $ = function(id){return document.getElementById(id) || null;}
        var wsServer = 'ws://127.0.0.1:8080'; 
        var ws = new WebSocket(wsServer);
        var isConnect = false;
        ws.onopen = function (evt) { onOpen(evt) }; 
        ws.onclose = function (evt) { onClose(evt) }; 
        ws.onmessage = function (evt) { onMessage(evt) }; 
        ws.onerror = function (evt) { onError(evt) }; 
        function onOpen(evt) { 
            console.log("       ");
            isConnect = true;
        } 
        function onClose(evt) { 
            //console.log("Disconnected"); 
        } 
        function onMessage(evt) {
            console.log('Retrieved data from server: ' + evt.data);
        }
        function onError(evt) { 
            //console.log('Error occured: ' + evt.data); 
        }
        function sendMsg() {
            if(isConnect){
                ws.send('hello');
            }
        }
    })();