一个简单的 websocket的 c++ 服务器 实现windows

时间比较匆忙, 写了一个简单的 websocket服务器,采用c++.   网络底层采用windows api.

等有空好好封装一下,让大家可以不关心细节,即可使用。  

//------主文件main.cpp-----------------------

#include "../../WebSocket/WebSocket.h"
#include "stdio.h"
#include "winsock2.h"
#include "sockio.h"
void main()
{
Server svr;
svr.WaitForClient();
//system("pause");
 printf("press Enter to Exit!");
 getchar();
}
//----------------------------------------------------

//--------------sockio.h--------------------------
#ifndef SERVER_H
#define SERVER_H
#include <Winsock2.h>
#include <windows.h>
#include "../../WebSocket/WebSocket.h"
#pragma comment (lib, "ws2_32.lib")
#define IP_BUF_SIZE 129
class Server
{
public:
    Server();
    ~Server();
 Server(const Server &);
    Server & operator=(const Server &);
    void WaitForClient();
private:
    WORD winsock_ver;
    WSADATA wsa_data;
    SOCKET sock_svr;
    SOCKET sock_clt;
    HANDLE h_thread;
    SOCKADDR_IN addr_svr;
    SOCKADDR_IN addr_clt;
    int ret_val;
    int addr_len;
    TCHAR buf_ip[IP_BUF_SIZE];
public:
 static WebSocket m_webSocket;
};
#endif
//---------------------------------------------------------------------

//---------------------sockio.cpp----------------------------------
#include "sockio.h"
#include <iostream>
#include <WS2tcpip.h>
using std::cerr;
using std::cout;
using std::endl;
#define SERVER_PORT 80
#define MSG_BUF_SIZE 1024
WebSocket Server::m_webSocket;
Server::Server()
{
    cout << "Initializing server...\n";
    //
    winsock_ver = MAKEWORD(2, 2);
    addr_len = sizeof(SOCKADDR_IN);
    addr_svr.sin_family = AF_INET;
    addr_svr.sin_port = ::htons(SERVER_PORT);
    addr_svr.sin_addr.S_un.S_addr = ADDR_ANY;
    memset(buf_ip, 0, IP_BUF_SIZE);
    //
    ret_val = ::WSAStartup(winsock_ver, &wsa_data);
    if (ret_val != 0)
    {
        cerr << "WSA failed to start up!Error code: " << ::WSAGetLastError() << "\n";
        system("pause");
        exit(1);
    }
    cout << "WSA started up successfully...\n";
    //
    sock_svr = ::socket(AF_INET, SOCK_STREAM, 0);
    if (sock_svr == INVALID_SOCKET)
    {
        cerr << "Failed to create server socket!Error code: " << ::WSAGetLastError() << "\n";
        ::WSACleanup();
        system("pause");
        exit(1);
    }
    cout << "Server socket created successfully...\n";
    //
    ret_val = ::bind(sock_svr, (SOCKADDR*)&addr_svr, addr_len);
    if (ret_val != 0)
    {
        cerr << "Failed to bind server socket!Error code: " << ::WSAGetLastError() << "\n";
        ::WSACleanup();
        system("pause");
        exit(1);
    }
    cout << "Server socket bound successfully...\n";
    //
    ret_val = ::listen(sock_svr, SOMAXCONN);
    if (ret_val == SOCKET_ERROR)
    {
        cerr << "Server socket failed to listen!Error code: " << ::WSAGetLastError() << "\n";
        ::WSACleanup();
        system("pause");
        exit(1);
    }
    cout << "Server socket started to listen...\n";
    //
    cout << "Server started successfully..." << endl;
}
Server::~Server()
{
    ::closesocket(sock_svr);
    ::closesocket(sock_clt);
    ::WSACleanup();
    cout << "Socket closed..." << endl;
}
DWORD WINAPI CreateClientThread(LPVOID lpParameter);
//
void Server::WaitForClient()
{
    while (true)
    {
        sock_clt = ::accept(sock_svr, (SOCKADDR*)&addr_clt, &addr_len);
        if (sock_clt == INVALID_SOCKET)
        {
            cerr << "Failed to accept client!Error code: " << ::WSAGetLastError() << "\n";
            ::WSACleanup();
            system("pause");
            exit(1);
        }
        ::InetNtop(addr_clt.sin_family, &addr_clt, buf_ip, IP_BUF_SIZE);
        cout << "A new client connected...IP address: " << buf_ip << ", port number: " << ::ntohs(addr_clt.sin_port) << endl;
        h_thread = ::CreateThread(nullptr, 0, CreateClientThread, (LPVOID)sock_clt, 0, nullptr);
        if (h_thread == NULL)
        {
            cerr << "Failed to create a new thread!Error code: " << ::WSAGetLastError() << "\n";
            ::WSACleanup();
            system("pause");
            exit(1);
        }
        ::CloseHandle(h_thread);
    }
}
void parseFrame(WebSocketFrameType frametype)
{/*
 ERROR_FRAME=0xFF00,
 INCOMPLETE_FRAME=0xFE00,
 OPENING_FRAME=0x3300,
 CLOSING_FRAME=0x3400,
 INCOMPLETE_TEXT_FRAME=0x01,
 INCOMPLETE_BINARY_FRAME=0x02,
 TEXT_FRAME=0x81,
 BINARY_FRAME=0x82,
 PING_FRAME=0x19,
 PONG_FRAME=0x1A
 */
 switch(frametype)
 {
 case ERROR_FRAME:
  break;
 case INCOMPLETE_FRAME:
  break;
 case OPENING_FRAME:
  break;
 case CLOSING_FRAME:
  break;
 case INCOMPLETE_TEXT_FRAME:
  break;
 case INCOMPLETE_BINARY_FRAME:
  break;
 case TEXT_FRAME:
  break;
 case BINARY_FRAME:
  break;
 case PING_FRAME:
  break;
 case PONG_FRAME:
  break;
 }
}
DWORD WINAPI CreateClientThread(LPVOID lpParameter)
{
 SOCKET sock_clt = (SOCKET)lpParameter;
    char buf_msg[MSG_BUF_SIZE];
 char sendbuf_msg[MSG_BUF_SIZE];
    int ret_val = 0;
 int snd_result = 0;
 int  count=0;
    do
    {
        memset(buf_msg, 0, MSG_BUF_SIZE);
  memset(sendbuf_msg, 0, MSG_BUF_SIZE);
        ret_val = ::recv(sock_clt, buf_msg, MSG_BUF_SIZE, 0);
        if (ret_val > 0)
        {
            if (strcmp(buf_msg, "exit") == 0)
            {
                cout << "Client requests to close the connection..." << endl;
                break;
            }
            cout << "Message received: " << buf_msg << endl;
   WebSocketFrameType frametype = Server::m_webSocket.parseHandshake((unsigned char*)buf_msg, ret_val);
   if(frametype == 1)
   {
   }
   parseFrame(frametype);
   
   count++;
   int len =0;
   string str;
   if(frametype == OPENING_FRAME)
   {
    str = Server::m_webSocket.answerHandshake();
    memcpy(sendbuf_msg, str.c_str(), str.length());
    len = str.length();
   }
   else if(frametype == INCOMPLETE_FRAME)
   {
    //sprintf(buf_msg, "666666");
    //ret_val = 6;
    Server::m_webSocket.getFrame((unsigned char*)buf_msg, ret_val, (unsigned char*)sendbuf_msg, MSG_BUF_SIZE, &len);
    sprintf(buf_msg,"%s[%d]",sendbuf_msg, count);
    ret_val = strlen(buf_msg);
    len = Server::m_webSocket.makeFrame(TEXT_FRAME, (unsigned char*)buf_msg, ret_val, (unsigned char*)sendbuf_msg, MSG_BUF_SIZE);
    
   }
   else
   {
   }
   snd_result = ::send(sock_clt,sendbuf_msg,len,0);
   if( snd_result == SOCKET_ERROR)
            {
                cerr << "Failed to send message to client!Error code: " << ::GetLastError() << "\n";
    ::closesocket(sock_clt);
                system("pause");
                return 1;
            }
   
   if(count > 100)
   {
    ret_val = strlen(buf_msg);
    len = Server::m_webSocket.makeFrame(CLOSING_FRAME, (unsigned char*)buf_msg, ret_val, (unsigned char*)sendbuf_msg, MSG_BUF_SIZE);
    snd_result = ::send(sock_clt,sendbuf_msg,len,0);
    if( snd_result == SOCKET_ERROR)
    {
     cerr << "Failed to send message to client!Error code: " << ::GetLastError() << "\n";
     ::closesocket(sock_clt);
     system("pause");
     return 1;
    }
    //::closesocket(sock_clt);
                //system("pause");
               // return 1;
   }
        }
        else if (ret_val == 0)
        {
            cout << "connection closed..." << endl;
        }
        else
        {
            cerr << "Failed to receive message from client!Error code: " << ::GetLastError() << "\n";
            ::closesocket(sock_clt);
            system("pause");
            return 1;
        }
    } while (ret_val > 0);
    //
    ret_val = ::shutdown(sock_clt, SD_SEND);
    if (ret_val == SOCKET_ERROR)
    {
        cerr << "Failed to shutdown the client socket!Error code: " << ::GetLastError() << "\n";
        ::closesocket(sock_clt);
        system("pause");
        return 1;
    }
    return 0;
}

//----------------------------------------------------------------------------------------------------------------------------------------------

//----------------------------websocket.h------------------------------------

#ifndef WEBSOCKET_H
#define WEBSOCKET_H
#include <assert.h>
#include <stdint.h> /* uint8_t */
#include <stdio.h> /* sscanf */
#include <ctype.h> /* isdigit */
#include <stddef.h> /* int */
// std c++
#include <vector>
#include <string>
using namespace std;
enum WebSocketFrameType {
 ERROR_FRAME=0xFF00,
 INCOMPLETE_FRAME=0xFE00,
 OPENING_FRAME=0x3300,
 CLOSING_FRAME=0x3400,
 INCOMPLETE_TEXT_FRAME=0x01,
 INCOMPLETE_BINARY_FRAME=0x02,
 TEXT_FRAME=0x81,
 BINARY_FRAME=0x82,
 PING_FRAME=0x19,
 PONG_FRAME=0x1A
};
class WebSocket
{
public:
 string resource;
 string host;
 string origin;
 string protocol;
 string key;
 WebSocket();
 /**
  * @param input_frame .in. pointer to input frame
  * @param input_len .in. length of input frame
  * @return [WS_INCOMPLETE_FRAME, WS_ERROR_FRAME, WS_OPENING_FRAME]
  */
 WebSocketFrameType parseHandshake(unsigned char* input_frame, int input_len);
 string answerHandshake();
 int makeFrame(WebSocketFrameType frame_type, unsigned char* msg, int msg_len, unsigned char* buffer, int buffer_len);
 WebSocketFrameType getFrame(unsigned char* in_buffer, int in_length, unsigned char* out_buffer, int out_size, int* out_length);
 string trim(string str);
 vector<string> explode(string theString, string theDelimiter, bool theIncludeEmptyStrings = false );
};
#endif /* WEBSOCKET_H */


//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------测试脚本-----------
<!DOCTYPE html> 
<meta charset="utf-8" /> 
<title>WebSocket Test</title> 
<script language="javascript"type="text/javascript"> 
    var wsUri ="ws://127.0.0.1:5000/";
    var output; 
   
    function init() {
        output = document.getElementById("output");
        testWebSocket();
    } 
 
    function testWebSocket() {
        websocket = new WebSocket(wsUri);
        websocket.onopen = function(evt) {
            onOpen(evt)
        };
        websocket.onclose = function(evt) {
            onClose(evt)
        };
        websocket.onmessage = function(evt) {
            onMessage(evt)
        };
        websocket.onerror = function(evt) {
            onError(evt)
        };
    } 
 
    function onOpen(evt) {
        writeToScreen("CONNECTED");
        doSend("WebSocket rocks");
    } 
 
    function onClose(evt) {
        writeToScreen("DISCONNECTED");
    } 
 
    function onMessage(evt) {
        writeToScreen('<span style="color: blue;">RESPONSE: '+ evt.data+'</span>');
        websocket.close();
    } 
 
    function onError(evt) {
        writeToScreen('<span style="color: red;">ERROR:</span> '+ evt.data);
    } 
 
    function doSend(message) {
        writeToScreen("SENT: " + message); 
        websocket.send(message);
    } 
 
    function writeToScreen(message) {
        var pre = document.createElement("p");
        pre.style.wordWrap = "break-word";
        pre.innerHTML = message;
        output.appendChild(pre);
    } 
 
    window.addEventListener("load", init, false); 
</script> 
<h2>WebSocket Test</h2> 
<div id="output"></div> 
</html>
//-----------------------------------------------------------------------------------------------------------------------------------------------

相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页