无法在 asio 中将 keep_alive 设置为套接字
Can't set keep_alive to socket in asio
我正在尝试将 ServerSocket 创建为单例。这是代码:
ServerSocket.h
#pragma once
#include <asio.hpp>
#include <iostream>
#include <optional>
using asio::ip::tcp;
class ServerSocket
{
public:
ServerSocket(ServerSocket& otherSingleton) = delete;
void operator= (const ServerSocket& copySingleton) = delete;
tcp::acceptor* InitAcceptor();
tcp::socket* InitSocket();
void StartServerSocket();
void SendData(std::string);
std::optional<std::string> RecieveData();
static ServerSocket* GetInstance();
private:
static ServerSocket* instance;
tcp::acceptor* acceptor;
tcp::socket* socket;
asio::io_context io_context;
ServerSocket()
{
acceptor = InitAcceptor();
socket = InitSocket();
}
~ServerSocket() {
delete socket;
delete acceptor;
std::cout << "Server closed";
}
};
ServerSocket.cpp
#include "ServerSocket.h"
#include <optional>
tcp::acceptor* ServerSocket::InitAcceptor()
{
try
{
return new tcp::acceptor(io_context, tcp::endpoint(tcp::v4(), 27015));
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return nullptr;
}
tcp::socket* ServerSocket::InitSocket()
{
try
{
tcp::socket* deReturnat = new tcp::socket(io_context);
asio::socket_base::keep_alive option(true);
deReturnat->set_option(option);
return deReturnat;
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return nullptr;
}
void ServerSocket::StartServerSocket()
{
try
{
std::cout << "Server started";
acceptor->accept(*socket);
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
}
void ServerSocket::SendData(std::string)
{
}
std::optional<std::string> ServerSocket::RecieveData()
{
try
{
char data[5000];
asio::error_code error;
size_t length = socket->read_some(asio::buffer(data), error);
if (error == asio::error::eof) return std::nullopt; // Connection closed cleanly by peer.
else if (error)
throw asio::system_error(error); // Some other error.
return std::string{ data, length };
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return {};
}
ServerSocket* ServerSocket::instance(nullptr);
ServerSocket* ServerSocket::GetInstance()
{
if (instance == nullptr)
{
instance = new ServerSocket();
}
return instance;
}
问题是在 InitSocket 中,当 运行 调试器时,似乎 set_option 由于某种原因不起作用,然后抛出异常 - 我无法理解为什么。
抛出的异常是:set_option: 提供的文件句柄无效。
如何在我的套接字中将 keep_alive 选项设置为 true?这种方式好像不行。
@Vasile,正如@dewaffed 告诉您的那样,您的问题是您在打开套接字之前设置选项。
我不知道您要做什么,但我可以看到您创建了一个未打开的新套接字并设置了属性,这就是问题所在。正确的方法是:
- 创建套接字
- 使用您之前创建的套接字接受新连接。
- 一旦接受器结束接受新连接,套接字就会有一个有效的文件描述符,这是在套接字上设置选项所必需的。
检查这些链接:
https://en.wikipedia.org/wiki/Berkeley_sockets
,其中谈到了你的异常。
https://www.boost.org/doc/libs/1_77_0/doc/html/boost_asio/tutorial/tutdaytime2.html
我正在尝试将 ServerSocket 创建为单例。这是代码:
ServerSocket.h
#pragma once
#include <asio.hpp>
#include <iostream>
#include <optional>
using asio::ip::tcp;
class ServerSocket
{
public:
ServerSocket(ServerSocket& otherSingleton) = delete;
void operator= (const ServerSocket& copySingleton) = delete;
tcp::acceptor* InitAcceptor();
tcp::socket* InitSocket();
void StartServerSocket();
void SendData(std::string);
std::optional<std::string> RecieveData();
static ServerSocket* GetInstance();
private:
static ServerSocket* instance;
tcp::acceptor* acceptor;
tcp::socket* socket;
asio::io_context io_context;
ServerSocket()
{
acceptor = InitAcceptor();
socket = InitSocket();
}
~ServerSocket() {
delete socket;
delete acceptor;
std::cout << "Server closed";
}
};
ServerSocket.cpp
#include "ServerSocket.h"
#include <optional>
tcp::acceptor* ServerSocket::InitAcceptor()
{
try
{
return new tcp::acceptor(io_context, tcp::endpoint(tcp::v4(), 27015));
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return nullptr;
}
tcp::socket* ServerSocket::InitSocket()
{
try
{
tcp::socket* deReturnat = new tcp::socket(io_context);
asio::socket_base::keep_alive option(true);
deReturnat->set_option(option);
return deReturnat;
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return nullptr;
}
void ServerSocket::StartServerSocket()
{
try
{
std::cout << "Server started";
acceptor->accept(*socket);
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
}
void ServerSocket::SendData(std::string)
{
}
std::optional<std::string> ServerSocket::RecieveData()
{
try
{
char data[5000];
asio::error_code error;
size_t length = socket->read_some(asio::buffer(data), error);
if (error == asio::error::eof) return std::nullopt; // Connection closed cleanly by peer.
else if (error)
throw asio::system_error(error); // Some other error.
return std::string{ data, length };
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return {};
}
ServerSocket* ServerSocket::instance(nullptr);
ServerSocket* ServerSocket::GetInstance()
{
if (instance == nullptr)
{
instance = new ServerSocket();
}
return instance;
}
问题是在 InitSocket 中,当 运行 调试器时,似乎 set_option 由于某种原因不起作用,然后抛出异常 - 我无法理解为什么。
抛出的异常是:set_option: 提供的文件句柄无效。
如何在我的套接字中将 keep_alive 选项设置为 true?这种方式好像不行。
@Vasile,正如@dewaffed 告诉您的那样,您的问题是您在打开套接字之前设置选项。
我不知道您要做什么,但我可以看到您创建了一个未打开的新套接字并设置了属性,这就是问题所在。正确的方法是:
- 创建套接字
- 使用您之前创建的套接字接受新连接。
- 一旦接受器结束接受新连接,套接字就会有一个有效的文件描述符,这是在套接字上设置选项所必需的。
检查这些链接:
https://en.wikipedia.org/wiki/Berkeley_sockets
https://www.boost.org/doc/libs/1_77_0/doc/html/boost_asio/tutorial/tutdaytime2.html