2016-04-11 11 views
2

asio kütüphanesini kullanarak C++ 'da bir sunucu kodu yazdım. Sunucu kodunun çalıştığını biliyorum, çünkü C++ ile yazılmış ve asio kullanarak bir istemci ile test ettim.İstemci olarak sunucu ve javascript için asio C++ kütüphanesini kullanan websockets

Sorun, istemci için aşağıdaki javascript kodu ile bağlantı kabul edilmez. Ben hemen javascript istemci üzerinde mesaj kutusu Connection closed... görmek ve sunucu üzerinde bu garip mesajı bakın:

Data RECEIVED: <------ I print this line myself 
GET/HTTP/1.1 
Host: localhost:15562 
Connection: Upgrade 
Pragma: no-cache 
Cache-Control: no-cache 
Upgrade: websocket 
Origin: http://localhost:63344 
Sec-WebSocket-Version: 13 
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.110 Safari/537.36 
Accept-Encoding: gzip, deflate, sdch 
Accept-Language: en-US,en;q=0.8 
Sec-WebSocket-Key: IidMJmdoGe4kYu0+1VlrvQ== 
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits 

index.html - görüldüğü gibi bağlantı sadece hemen kapatır ... Neredeyse aynı kodu here

function WebSocketTest() { 
    if ("WebSocket" in window) { 
     var ws = new WebSocket("ws://localhost:15562"); 

     ws.onopen = function() { 
      alert("Connection opened..."); 
     }; 

     ws.onmessage = function (evt) { 
      alert("Message received..."); 
     }; 

     ws.onclose = function() { 
      alert("Connection closed..."); 
     }; 

     ws.send("Hi, from the client"); 
     ws.send("Hi, from the client"); 
    } 
} 

server.cpp - Bu iyi çalışıyor. Bu iyi çalışır - here

#define ASIO_STANDALONE 
#include <iostream> 
#include <asio.hpp> 

using asio::ip::tcp; 

const std::size_t max_length = 2048; 
const unsigned short PORT  = 15562; 


class Session 
    : public std::enable_shared_from_this<Session> 
{ 
public: 
    Session(tcp::socket server_socket) 
     : _session_socket(std::move(server_socket)) 
    { 
    } 

    void start() 
    { 
     do_read(); 
    } 

private: 
    void do_read() 
    { 
     auto self(shared_from_this()); // shared_ptr instance to this 

     // Start an asynchronous read. 
     // This function is used to asynchronously read data from the stream socket. 
     _session_socket.async_read_some(asio::buffer(_data, max_length), 
             [this, self](std::error_code error, std::size_t length) 
             { 
              if (!error) 
              { 
               std::cout << "Data RECEIVED: " << std::endl; 
               std::cout << _data << std::endl; 
               do_write(length); 
              } 
             }); 
    } 

    void do_write(std::size_t length) 
    { 
     auto self(shared_from_this()); // shared_ptr instance to this 

     // Start an asynchronous write. 
     // This function is used to asynchronously write data to the stream socket. 
     strncpy(_data, "Hi, from the server", max_length); 
     asio::async_write(_session_socket, asio::buffer(_data, length), 
          [this, self](std::error_code error, std::size_t /*length*/) 
          { 
           if (!error) 
           { 
            do_read(); 
           } 
          }); 
    } 

    tcp::socket _session_socket; 
    char  _data[max_length]; 
}; 


class server 
{ 
public: 
    server(asio::io_service &io_service, const tcp::endpoint &endpoint) 
     : _server_socket(io_service), 
      _server_acceptor(io_service, endpoint) 
    { 
    } 

    void do_accept() 
    { 
     // Start an asynchronous accept. 
     // This function is used to asynchronously accept a new connection into a socket. 
     _server_acceptor.async_accept(_server_socket, 
             [this](std::error_code error) 
             { 
              // Accept succeeded 
              if (!error) 
              { 
               // Create a session 
               auto session = std::make_shared<Session>(
                std::move(_server_socket)); 
               session->start(); 
              } 

              // Continue to accept more connections 
              do_accept(); 
             }); 
    } 

private: 
    tcp::acceptor _server_acceptor; 
    tcp::socket _server_socket; 
}; 


int main() 
{ 
    try 
    { 
     asio::io_service io_service;     // io_service provides functionality for sockets, connectors, etc 
     tcp::endpoint endpoint(tcp::v4(), PORT); // create an endpoint using a IP='any' and the specified PORT 
     server   server(io_service, endpoint); // create server on PORT 
     server.do_accept(); 
     std::cout << "Server started on port: " << PORT << std::endl; 
     io_service.run(); 
    } 
    catch (std::exception &e) 
    { 
     std::cerr << "Exception: " << e.what() << "\n"; // Print error 
    } 

    return 0; 
} 

client.cpp görüldüğü gibi hemen hemen aynı kodu.

#define ASIO_STANDALONE 
#include <iostream> 
#include <asio.hpp> 

using asio::ip::tcp; 


int main(int argc, char *argv[]) 
{ 
    asio::io_service io_service; 
    tcp::socket  socket(io_service); 
    tcp::resolver resolver(io_service); 
    // Connect 
    asio::connect(socket, resolver.resolve({"localhost", "15562"})); 

    for (int i = 0; i < 10; ++i) 
    { 
     std::cout << "Enter message to sent to server:" << std::endl; 
     char client_message[2048]; 
     std::cin.getline(client_message, 2048); 
     // Send message to server 
     asio::write(socket, asio::buffer(client_message, 2048)); 

     char server_message[2048]; 
     // Read message from server 
     asio::read(socket, asio::buffer(server_message, 2048)); 
     std::cout << "Reply is: " << std::endl; 
     std::cout << server_message << std::endl; 
    } 

    return 0; 
} 
+0

Hey, bu sorunu çözdünüz mü? –

+0

@MichaelIvanov Sorun, soketleri ve web kartuşlarını birleştirmeyi denediğimdi. Bu yüzden işe yaramadı. Cpp tarafındaki websockets'a ihtiyacım vardı. – dimitris93

+0

Yani kendiniz mi yazdınız ya da biraz lib kullanıyorsunuz? Lütfen bir cevap ekleyebilir misiniz? Bu bilgi ile çok ilgileniyorum. Teşekkürler! –

cevap

1

here seninki javascript kodu sivri başlık gönderme ve benzeri başlığını bekliyor görüldüğü gibi hemen hemen aynı kodu:

HTTP/1.1 101 Switching Protocols 
Upgrade: websocket 
Connection: Upgrade 
Sec-WebSocket-Accept: 5A4gqmvwM2kbopObEm+Kr6zBrNw= 
Sec-WebSocket-Protocol: echo-protocol 

Ama tam da aynı başlığını geri göndermek. Doğru değil. Yani "Bağlantı kapalı ..." oluyorsunuz. Sec-WebSocket-Accept için üstbilgiyi doğru değeriyle yapmanız gerekir.

Örneğin, do_write yöntemi Burada

void do_write(std::size_t length) 
    { 
    auto self(shared_from_this()); 

    std::stringstream handshake; 

    std::string tmp(data_); 
    tmp.erase(0, tmp.find("Sec-WebSocket-Key: ") + strlen("Sec-WebSocket-Key: ")); 
    auto key = tmp.substr(0, tmp.find("\r\n")); 

    auto sha1 = SimpleWeb::Crypto::SHA1(key + ws_magic_string); 

    handshake << "HTTP/1.1 101 Switching Protocols\r\n"; 
    handshake << "Upgrade: websocket\r\n"; 
    handshake << "Connection: Upgrade\r\n"; 
    handshake << "Sec-WebSocket-Accept: " << SimpleWeb::Crypto::Base64::encode(sha1) << "\r\n"; 
    handshake << "Sec-WebSocket-Protocol: echo-protocol\r\n"; 
    handshake << "\r\n"; 

    boost::asio::async_write(socket_, boost::asio::buffer(handshake.str().c_str(), handshake.str().size()), 
     [this, self](boost::system::error_code ec, std::size_t /*length*/) 
     { 
      if (!ec) 
      { 
      do_read(); 
      } 
     }); 
    } 

görünebilir i projenin https://github.com/eidheim/Simple-WebSocket-Server gelen Kripto yöntemlerini kullanılan

const std::string ws_magic_string = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; 

İyi şanslar olarak ws_magic_string orada tanımladı.

İlgili konular