TcpServer类继承自TcpSocket,提供了server的初始化和连接功能。
namespace industrial
{
namespace tcp_server
{
class TcpServer : public industrial::tcp_socket::TcpSocket
{
public:
TcpServer();
~TcpServer();
bool init(int port_num);
// Overrides
bool makeConnect();
protected:
int srvr_handle_;
int getSrvrHandle() const
{
return srvr_handle_;
}
void setSrvrHandle(int srvr_handle_)
{
this->srvr_handle_ = srvr_handle_;
}
};
} //simple_socket
} //industrial
init
bool TcpServer::init(int port_num)
{
int rc;
bool rtn;
const int reuse_addr = 1;
//int err;
SOCKLEN_T addrSize = 0;
rc = SOCKET(AF_INET, SOCK_STREAM, 0);
if (this->SOCKET_FAIL != rc)
{
this->setSrvrHandle(rc);
LOG_DEBUG("Socket created, rc: %d", rc);
LOG_DEBUG("Socket handle: %d", this->getSrvrHandle());
SET_REUSE_ADDR(this->getSrvrHandle(), reuse_addr);
// Initialize address data structure
memset(&this->sockaddr_, 0, sizeof(this->sockaddr_));
this->sockaddr_.sin_family = AF_INET;
this->sockaddr_.sin_addr.s_addr = INADDR_ANY;
this->sockaddr_.sin_port = HTONS(port_num);
addrSize = sizeof(this->sockaddr_);
rc = BIND(this->getSrvrHandle(), (sockaddr *)&(this->sockaddr_), addrSize);
if (this->SOCKET_FAIL != rc)
{
LOG_INFO("Server socket successfully initialized");
rc = LISTEN(this->getSrvrHandle(), 1);
if (this->SOCKET_FAIL != rc)
{
LOG_INFO("Socket in listen mode");
rtn = true;
}
else
{
LOG_ERROR("Failed to set socket to listen");
rtn = false;
}
}
else
{
LOG_ERROR("Failed to bind socket, rc: %d", rc);
CLOSE(this->getSrvrHandle());
rtn = false;
}
}
else
{
LOG_ERROR("Failed to create socket, rc: %d", rc);
rtn = false;
}
return rtn;
}
init
方法用于TCP server的初始化,依次调用socket创建套接字,调用bind绑定地址,最后调用listen启动服务端的监听,等待客户端的连接请求。
this->setSrvrHandle(rc)
用于将创建好的监听socket描述符保存至本地,以便将来恢复连接时使用。
makeConnect
bool TcpServer::makeConnect()
{
bool rtn = false;
int rc = this->SOCKET_FAIL;
//int socket = this->SOCKET_FAIL;
int disableNodeDelay = 1;
int err = 0;
if (!this->isConnected())
{
this->setConnected(false);
if (this->SOCKET_FAIL != this->getSockHandle())
{
CLOSE(this->getSockHandle());
this->setSockHandle(this->SOCKET_FAIL);
}
rc = ACCEPT(this->getSrvrHandle(), NULL, NULL);
if (this->SOCKET_FAIL != rc)
{
this->setSockHandle(rc);
LOG_INFO("Client socket accepted");
// The set no delay disables the NAGEL algorithm
rc = SET_NO_DELAY(this->getSockHandle(), disableNodeDelay);
err = errno;
if (this->SOCKET_FAIL == rc)
{
LOG_WARN("Failed to set no socket delay, errno: %d, sending data can be delayed by up to 250ms", err);
}
this->setConnected(true);
rtn = true;
}
else
{
LOG_ERROR("Failed to accept for client connection");
rtn = false;
}
}
else
{
LOG_WARN("Tried to connect when socket already in connected state");
}
return rtn;
}
makeConnect用于接受客户端连接请求,由accept函数完成。并保存连接socket描述符,以备和客户端之间的发送接收时使用。至此,一个可用的TcpServer就完成了。
网友评论