openwrt上写一个简单的websocket服务器
时间: 2023-07-31 13:09:27 浏览: 217
一个简单的web服务器
4星 · 用户满意度95%
在 OpenWrt 上编写 WebSocket 服务器需要使用 C/C++ 或其他语言,并使用相应的库来实现 WebSocket 协议。以下是一个使用 C++ 和 Boost.Asio 库编写的简单 WebSocket 服务器示例:
1. 首先,安装必要的软件包,包括 boost,libopenssl 和 libpthread:
```
opkg update
opkg install libboost-system libboost-filesystem libopenssl libpthread
```
2. 创建一个名为 `websocket_server.cpp` 的文件,并将以下代码复制到其中:
```c++
#include <iostream>
#include <string>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/algorithm/string.hpp>
using boost::asio::ip::tcp;
class websocket_session : public boost::enable_shared_from_this<websocket_session>
{
public:
websocket_session(boost::asio::io_service& io_service, boost::asio::ssl::context& context)
: socket_(io_service, context)
{
}
tcp::socket& socket()
{
return socket_.next_layer();
}
void start()
{
socket_.async_handshake(boost::asio::ssl::stream_base::server,
boost::bind(&websocket_session::handle_handshake, shared_from_this(),
boost::asio::placeholders::error));
}
private:
void handle_handshake(const boost::system::error_code& error)
{
if (!error)
{
boost::asio::async_read_until(socket_, request_, "\r\n\r\n",
boost::bind(&websocket_session::handle_request, shared_from_this(),
boost::asio::placeholders::error));
}
}
void handle_request(const boost::system::error_code& error)
{
if (!error)
{
std::istream request_stream(&request_);
std::string header;
while (std::getline(request_stream, header) && header != "\r")
{
std::vector<std::string> tokens;
boost::split(tokens, header, boost::is_any_of(":"));
if (tokens.size() == 2 && tokens[0] == "Sec-WebSocket-Key")
{
std::string key = tokens[1] + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
std::string sha1_key = boost::asio::detail::sha1(key);
std::string accept_key = boost::asio::detail::base64_encode(
reinterpret_cast<const unsigned char*>(sha1_key.c_str()), sha1_key.length());
boost::asio::streambuf response;
std::ostream response_stream(&response);
response_stream << "HTTP/1.1 101 Switching Protocols\r\n"
<< "Upgrade: websocket\r\n"
<< "Connection: Upgrade\r\n"
<< "Sec-WebSocket-Accept: " << accept_key << "\r\n\r\n";
boost::asio::async_write(socket_, response,
boost::bind(&websocket_session::handle_write, shared_from_this(),
boost::asio::placeholders::error));
return;
}
}
}
}
void handle_write(const boost::system::error_code& error)
{
if (!error)
{
boost::asio::async_read(socket_, boost::asio::buffer(buffer_),
boost::asio::transfer_at_least(1),
boost::bind(&websocket_session::handle_read, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
}
void handle_read(const boost::system::error_code& error, std::size_t bytes_transferred)
{
if (!error)
{
std::ostream response_stream(&response_);
response_stream << "HTTP/1.1 200 OK\r\n"
<< "Content-Type: text/plain\r\n"
<< "Content-Length: " << bytes_transferred << "\r\n\r\n";
response_stream.write(buffer_.data(), bytes_transferred);
boost::asio::async_write(socket_, response_,
boost::bind(&websocket_session::handle_write, shared_from_this(),
boost::asio::placeholders::error));
}
}
boost::asio::ssl::stream<tcp::socket> socket_;
boost::asio::streambuf request_;
boost::asio::streambuf response_;
boost::array<char, 8192> buffer_;
};
class websocket_server
{
public:
websocket_server(boost::asio::io_service& io_service, unsigned short port)
: io_service_(io_service),
acceptor_(io_service, tcp::endpoint(tcp::v4(), port)),
context_(boost::asio::ssl::context::sslv23)
{
context_.set_options(boost::asio::ssl::context::default_workarounds
| boost::asio::ssl::context::no_sslv2
| boost::asio::ssl::context::single_dh_use);
context_.set_password_callback(boost::bind(&websocket_server::get_password, this));
context_.use_certificate_chain_file("server.crt");
context_.use_private_key_file("server.key", boost::asio::ssl::context::pem);
start_accept();
}
std::string get_password() const
{
return "test";
}
private:
void start_accept()
{
websocket_session::pointer new_session = websocket_session::create(io_service_, context_);
acceptor_.async_accept(new_session->socket(),
boost::bind(&websocket_server::handle_accept, this, new_session,
boost::asio::placeholders::error));
}
void handle_accept(websocket_session::pointer new_session, const boost::system::error_code& error)
{
if (!error)
{
new_session->start();
start_accept();
}
}
boost::asio::io_service& io_service_;
tcp::acceptor acceptor_;
boost::asio::ssl::context context_;
};
int main(int argc, char* argv[])
{
try
{
if (argc != 2)
{
std::cerr << "Usage: websocket_server <port>\n";
return 1;
}
boost::asio::io_service io_service;
websocket_server server(io_service, std::atoi(argv[1]));
io_service.run();
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
```
3. 编译代码:
```
g++ -o websocket_server websocket_server.cpp -lboost_system -lboost_filesystem -lboost_thread -lssl -lcrypto -lpthread
```
4. 运行服务器:
```
./websocket_server 8080
```
现在,WebSocket 服务器已经在 OpenWrt 上启动,并监听端口 8080。您可以使用 WebSocket 客户端连接到该服务器并进行交互。
阅读全文