C++ I/O 多路复用服务器过早关闭连接
C++ I/O Multiplexed server closes connections prematurely
我写了一套基本的C++网络编程classes(无非是一个tcp_socket一个udp_socket和一个ip_address wrap class class)。
我在使用 I/O 多路复用服务器时遇到了一些问题。
让我解释一下:
场景是这样的:
class base_socket
{
//code for all sockets methods (both tcp and udp this class throws
//errors and derived classes will cathc them.
~base_socket() { ::close(sock_fd); }
};
class udp_socket : public base_socket
{
//code for the udp_socket
virtual ~udp_socket();
};
class tcp_socket : public base_socket
{
//code for the tcp_socket
virtual ~tcp_socket();
};
在这个方案中,根据应用程序的上下文,我添加了一个
别有用心的抽象层次:类似于
class client_t : public tcp_socket
{
//code for dependent client tasks
};
主要程序代码是这样的
int main(int argc , char *[] argv)
{
int maxfd;
fd_set rset;
std::vector<base_socket> clientsV;
while(1)
{
FD_ZERO( &rset);
FD_SET( {/*listening socket fd*/, &rset);
if( clientsV.size() > 0)
maxfd = // socket fd with max value between sockets
else
maxfd = //listen socket
for (auto it = clientsV.begin() ; it != clientsV.end(); ++it)
FD_SET( /*client's socket fd*/, &rset);
select( maxfd+1, &rset, NULL, NULL, NULL) < 0);
if( FD_ISSET( /*listeing_socket*/, &rset))
{
client_t * newclient = new client_t();
listening_socket.accept(newclient);
newClient->send_message("HELO");
clientsV.push_back(*newClient);
}
}
}
这适用于第一个客户端,但当第二个客户端到来时,它会收到 HELO 响应,但在第二个 clientsV.push_back(*newClient) 上,第一个连接已关闭 ()。知道出了什么问题吗?
您的 clientsV
成员应该是 std::vector<base_socket*>
(即保留指针引用)。如果需要将现有元素重新定位到不同的区域(请参阅 Why does vector::push_back and emplace_back call value_type::constructor twice?),您有可能在 push_back
期间创建和销毁临时 client_t
对象。
发生这种情况时,将调用 ~client_t()
并关闭套接字。
此外,您有内存泄漏。您正在使用 new
分配一个指针,但您存储了取消引用的副本。您真的应该按原样存储指针(并在需要时管理 delete
ing 它)。
我写了一套基本的C++网络编程classes(无非是一个tcp_socket一个udp_socket和一个ip_address wrap class class)。 我在使用 I/O 多路复用服务器时遇到了一些问题。 让我解释一下:
场景是这样的:
class base_socket
{
//code for all sockets methods (both tcp and udp this class throws
//errors and derived classes will cathc them.
~base_socket() { ::close(sock_fd); }
};
class udp_socket : public base_socket
{
//code for the udp_socket
virtual ~udp_socket();
};
class tcp_socket : public base_socket
{
//code for the tcp_socket
virtual ~tcp_socket();
};
在这个方案中,根据应用程序的上下文,我添加了一个 别有用心的抽象层次:类似于
class client_t : public tcp_socket
{
//code for dependent client tasks
};
主要程序代码是这样的
int main(int argc , char *[] argv)
{
int maxfd;
fd_set rset;
std::vector<base_socket> clientsV;
while(1)
{
FD_ZERO( &rset);
FD_SET( {/*listening socket fd*/, &rset);
if( clientsV.size() > 0)
maxfd = // socket fd with max value between sockets
else
maxfd = //listen socket
for (auto it = clientsV.begin() ; it != clientsV.end(); ++it)
FD_SET( /*client's socket fd*/, &rset);
select( maxfd+1, &rset, NULL, NULL, NULL) < 0);
if( FD_ISSET( /*listeing_socket*/, &rset))
{
client_t * newclient = new client_t();
listening_socket.accept(newclient);
newClient->send_message("HELO");
clientsV.push_back(*newClient);
}
}
}
这适用于第一个客户端,但当第二个客户端到来时,它会收到 HELO 响应,但在第二个 clientsV.push_back(*newClient) 上,第一个连接已关闭 ()。知道出了什么问题吗?
您的 clientsV
成员应该是 std::vector<base_socket*>
(即保留指针引用)。如果需要将现有元素重新定位到不同的区域(请参阅 Why does vector::push_back and emplace_back call value_type::constructor twice?),您有可能在 push_back
期间创建和销毁临时 client_t
对象。
发生这种情况时,将调用 ~client_t()
并关闭套接字。
此外,您有内存泄漏。您正在使用 new
分配一个指针,但您存储了取消引用的副本。您真的应该按原样存储指针(并在需要时管理 delete
ing 它)。