亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

WebSocket的C++服務器端實現

2019-11-06 08:54:09
字體:
來源:轉載
供稿:網友

WebSocket的C++服務器端實現

  由于需要在項目中增加Websocket協議,與客戶端進行通信,不想使用開源的庫,比如WebSocketPP,就自己根據WebSocket協議實現一套函數,完全使用C++實現。

代碼已經實現,放在個人github上面,地址:https://github.com/jice1001/websocket.git。下面進行解釋說明:

一、原理

  Websocket協議解析,已經在前面博客里面詳細講解過,可以參考博客http://www.cnblogs.com/jice1990/p/5435419.html,這里就不詳細細說。

服務器端實現就是使用TCP協議,使用傳統的socket流程進行綁定監聽,使用epoll控制多路并發,收到Websocket握手包時候進行握手處理,握手成功便可進行數據收發。

二、實現

  1、服務器監聽

  該部分使用的是TCP socket流程,首先是通過socket函數建立socket,通過bind函數綁定到某個端口,本例使用的是9000,然后通過listen函數開啟監聽,代碼如下:

復制代碼
    listenfd_ = socket(AF_INET, SOCK_STREAM, 0);    if(listenfd_ == -1){        DEBUG_LOG("創建套接字失敗!");        return -1;    }    struct sockaddr_in server_addr;    memset(&server_addr, 0, sizeof(sockaddr_in));    server_addr.sin_family = AF_INET;    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);    server_addr.sin_port = htons(PORT);    if(-1 == bind(listenfd_, (struct sockaddr *)(&server_addr), sizeof(server_addr))){        DEBUG_LOG("綁定套接字失敗!");        return -1;    }    if(-1 == listen(listenfd_, 5)){        DEBUG_LOG("監聽失敗!");        return -1;    }復制代碼

  2、epoll控制多路并發

  該部分使用的是epoll流程,首先在初始化時候使用epoll_create創建epoll句柄

epollfd_ = epoll_create(1024);

  然后通過epoll_wait等待fd事件來臨,當監聽到是listenfd事件時候,說明是客戶端連接服務器,就使用accept接受連接,然后注冊該連接EPOLLIN事件,當epoll監聽到EPOLLIN事件時候,即可進行握手和數據讀取。代碼如下:

復制代碼
void ctl_event(int fd, bool flag){    struct epoll_event ev;    ev.data.fd = fd;    ev.events = flag ? EPOLLIN : 0;    epoll_ctl(epollfd_, flag ? EPOLL_CTL_ADD : EPOLL_CTL_DEL, fd, &ev);    if(flag){        set_noblock(fd);        websocket_handler_map_[fd] = new Websocket_Handler(fd);        if(fd != listenfd_)            DEBUG_LOG("fd: %d 加入epoll循環", fd);    }    else{        close(fd);        delete websocket_handler_map_[fd];        websocket_handler_map_.erase(fd);        DEBUG_LOG("fd: %d 退出epoll循環", fd);    }}復制代碼復制代碼
int epoll_loop(){    struct sockaddr_in client_addr;    socklen_t clilen;    int nfds = 0;    int fd = 0;    int bufflen = 0;    struct epoll_event events[MAXEVENTSSIZE];    while(true){        nfds = epoll_wait(epollfd_, events, MAXEVENTSSIZE, TIMEWAIT);        for(int i = 0; i < nfds; i++){            if(events[i].data.fd == listenfd_){                fd = accept(listenfd_, (struct sockaddr *)&client_addr, &clilen);                ctl_event(fd, true);            }            else if(events[i].events & EPOLLIN){                if((fd = events[i].data.fd) < 0)                    continue;                Websocket_Handler *handler = websocket_handler_map_[fd];                if(handler == NULL)                    continue;                if((bufflen = read(fd, handler->getbuff(), BUFFLEN)) <= 0){                    ctl_event(fd, false);                }                else{                    handler->PRocess();                }            }        }    }    return 0;}復制代碼

  3、Websocket握手連接

  握手部分主要是根據Websocket握手包進行解析,然后根據Sec-WebSocket-Key進行SHA1哈希,生成相應的key,返回給客戶端,與客戶端進行握手。代碼如下:

復制代碼
//該函數是獲取websocket握手包的信息,按照分割字符進行解析int fetch_http_info(){    std::istringstream s(buff_);    std::string request;    std::getline(s, request);    if (request[request.size()-1] == '/r') {        request.erase(request.end()-1);    } else {        return -1;    }    std::string header;    std::string::size_type end;    while (std::getline(s, header) && header != "/r") {        if (header[header.size()-1] != '/r') {            continue; //end        } else {            header.erase(header.end()-1);    //remove last char        }        end = header.find(": ",0);        if (end != std::string::npos) {            std::string key = header.substr(0,end);            std::string value = header.substr(end+2);            header_map_[key] = value;        }    }    return 0;}復制代碼復制代碼
//該函數是根據websocket返回包的格式拼接相應的返回包void parse_str(char *request){      strcat(request, "HTTP/1.1 101 Switching Protocols/r/n");    strcat(request, "Connection: upgrade/r/n");    strcat(request, "Sec-WebSocket-Accept: ");    std::string server_key = header_map_["Sec-WebSocket-Key"];    server_key += MAGIC_KEY;    SHA1 sha;    unsigned int message_digest[5];    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/n";    strcat(request, server_key.c_str());    strcat(request, "Upgrade: websocket/r/n/r/n");}復制代碼

  4、數據讀取

  當服務器與客戶端握手成功后,就可以進行正常的通信,讀取數據了。使用的是TCP協議的方法,解析Websocket包根據協議格式,在前面博客里面有詳細分析,這里只把實現代碼貼出來。

復制代碼
int fetch_websocket_info(char *msg){    int pos = 0;    fetch_fin(msg, pos);    fetch_opcode(msg, pos);    fetch_mask(msg, pos);    fetch_payload_length(msg, pos);    fetch_masking_key(msg, pos);    return fetch_payload(msg, pos);}int fetch_fin(char *msg, int &pos){    fin_ = (unsigned char)msg[pos] >> 7;    return 0;}int fetch_opcode(char *msg, int &pos){    opcode_ = msg[pos] & 0x0f;    pos++;    return 0;}int fetch_mask(char *msg, int &pos){    mask_ = (unsigned char)msg[pos] >> 7;    return 0;}int fetch_masking_key(char *msg, int &pos){    if(mask_ != 1)        return 0;    for(int i = 0; i < 4; i++)        masking_key_[i] = msg[pos + i];    pos += 4;    return 0;}int fetch_payload_length(char *msg, int &pos){    payload_length_ = msg[pos] & 0x7f;    pos++;    if(payload_length_ == 126){        uint16_t length = 0;        memcpy(&length, msg + pos, 2);        pos += 2;        payload_length_ = ntohs(length);    }    else if(payload_length_ == 127){        uint32_t length = 0;        memcpy(&length, msg + pos, 4);        pos += 4;        payload_length_ = ntohl(length);    }    return 0;}int fetch_payload(char *msg, int &pos){    memset(payload_, 0, sizeof(payload_));    if(mask_ != 1){        memcpy(payload_, msg + pos, payload_length_);    }    else {        for(uint i = 0; i < payload_length_; i++){            int j = i % 4;            payload_[i] = msg[pos + i] ^ masking_key_[j];        }    }    pos += payload_length_;    return 0;}復制代碼

  5、總結

  到此為止,完整實現了使用C++對Websocket協議進行解析,握手,數據收發,不借助開源庫就實現了websocket相關功能,最大程度的與項目保存兼容。

 


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
色中色综合影院手机版在线观看| 韩曰欧美视频免费观看| 日韩在线观看免费| 久久影视电视剧免费网站| 九九热这里只有精品免费看| 日韩精品在线播放| 精品亚洲一区二区| 国产精品视频精品视频| 欧美一级视频一区二区| 国内精品久久久久久中文字幕| 欧美精品在线视频观看| 亚洲国产精品小视频| 日本精品va在线观看| 日本久久亚洲电影| 成人免费看吃奶视频网站| 欧美激情xxxxx| 中文字幕亚洲一区二区三区| 91免费的视频在线播放| 国产精品香蕉av| 国模吧一区二区三区| 最新69国产成人精品视频免费| 色播久久人人爽人人爽人人片视av| 欧美激情影音先锋| 欧美日韩另类在线| 日韩欧美在线第一页| 人人澡人人澡人人看欧美| 亚洲跨种族黑人xxx| 国产成人久久精品| 欧美激情视频一区| 欧美精品在线网站| 欧美国产亚洲精品久久久8v| 1769国内精品视频在线播放| 欧美激情综合色| 91在线|亚洲| 91av视频在线观看| 精品无人区乱码1区2区3区在线| 日韩电视剧在线观看免费网站| 亚洲最大福利网站| 欧美床上激情在线观看| 欧美激情亚洲视频| 91免费国产视频| 国产日韩av在线播放| 久久久久久久久久久av| 欧美电影免费观看电视剧大全| 狠狠躁18三区二区一区| 亚洲欧美日韩一区二区在线| 国产精品中文久久久久久久| 欧美国产日韩免费| 国产人妖伪娘一区91| 亚洲久久久久久久久久| 欧美极品少妇全裸体| 亚洲天堂av电影| 日韩av免费在线| 亚洲xxxx做受欧美| 亚洲国产高清高潮精品美女| 久久精品国产精品亚洲| 欧美福利视频在线观看| 久久6免费高清热精品| 欧美天天综合色影久久精品| 精品成人在线视频| 91国内揄拍国内精品对白| 国色天香2019中文字幕在线观看| 中文字幕亚洲欧美日韩高清| 欧美成人h版在线观看| 韩国美女主播一区| 久久av在线看| 欧美大片va欧美在线播放| 青青草国产精品一区二区| 精品欧美aⅴ在线网站| 操日韩av在线电影| 91爱爱小视频k| 欧美日韩亚洲精品内裤| 久久伊人精品天天| 亚洲直播在线一区| 中文字幕一区电影| 色综合久久久久久中文网| 亚洲人成网站999久久久综合| 国产一区二区在线免费视频| 尤物99国产成人精品视频| 久久久国产影院| 日韩在线观看网站| 精品女同一区二区三区在线播放| 亚洲午夜性刺激影院| 国产在线高清精品| 精品久久久久久电影| 91沈先生在线观看| 久久亚洲精品中文字幕冲田杏梨| 久久久久久久一| 国产精品99久久久久久久久久久久| 一区二区成人av| 久久久久久网址| 亚洲精品欧美一区二区三区| 精品国产老师黑色丝袜高跟鞋| 国语自产精品视频在免费| 亚洲成人av片| 日韩精品免费在线| 久久男人资源视频| 亚洲国产欧美久久| 久久久久亚洲精品| 国产精品久久久久秋霞鲁丝| 成人精品视频99在线观看免费| 亚洲无限av看| 欧美一区二区大胆人体摄影专业网站| 欧美国产日韩精品| 欧美激情性做爰免费视频| 中文字幕国内精品| 九九热视频这里只有精品| 色妞一区二区三区| 国产精品99久久久久久白浆小说| 国产美女久久精品香蕉69| 亚洲欧美日韩精品久久奇米色影视| 在线视频精品一| 国产精品高潮呻吟久久av无限| 国产在线精品播放| 亚洲第一网站男人都懂| 欧美激情免费在线| 日韩av中文字幕在线免费观看| 欧美激情视频三区| 亚洲一区二区三区四区在线播放| 亚洲欧美综合另类中字| 69视频在线播放| 97在线视频免费| 懂色av中文一区二区三区天美| 欧美激情精品久久久久| 亚洲三级黄色在线观看| 91av成人在线| 亚洲免费成人av电影| 上原亚衣av一区二区三区| 日韩av在线最新| 久久久免费观看| 欧美xxxx做受欧美.88| 亚洲视频电影图片偷拍一区| 成人情趣片在线观看免费| 68精品国产免费久久久久久婷婷| 欧美午夜精品久久久久久浪潮| 92国产精品久久久久首页| 日日骚久久av| 一二美女精品欧洲| 亚洲人成网站免费播放| 91精品成人久久| 亚洲女性裸体视频| 欧美肥臀大乳一区二区免费视频| 爽爽爽爽爽爽爽成人免费观看| 最新国产精品拍自在线播放| 色妞一区二区三区| 精品五月天久久| 丰满岳妇乱一区二区三区| 亚洲成人激情视频| 日韩精品高清在线观看| 精品久久久久久久久国产字幕| 日韩中文字幕国产精品| 欧美精品videos性欧美| 国产精品偷伦免费视频观看的| 欧美一级电影在线| 91色在线观看| 亚洲精品在线视频| 亚洲最大成人免费视频| 久久久女女女女999久久| 亚洲欧美中文另类| 日韩精品一区二区视频| 国产日韩av在线| 亚洲高清在线观看| 久久久亚洲欧洲日产国码aⅴ| 国产精品成人免费视频|