91 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			91 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			C++
		
	
	
	
| #include "TcpServer.h"
 | |
| #include "Acceptor.h"
 | |
| #include "EventLoop.h"
 | |
| #include "Logger.h"
 | |
| #include <cstdio>  
 | |
| 
 | |
| using namespace xop;
 | |
| using namespace std;
 | |
| 
 | |
| TcpServer::TcpServer(EventLoop* event_loop)
 | |
| 	: event_loop_(event_loop)
 | |
| 	, port_(0)
 | |
| 	, acceptor_(new Acceptor(event_loop_))
 | |
| 	, is_started_(false)
 | |
| {
 | |
| 	acceptor_->SetNewConnectionCallback([this](SOCKET sockfd) {
 | |
| 		TcpConnection::Ptr conn = this->OnConnect(sockfd);
 | |
| 		if (conn) {
 | |
| 			this->AddConnection(sockfd, conn);
 | |
| 			conn->SetDisconnectCallback([this](TcpConnection::Ptr conn) {
 | |
| 				auto scheduler = conn->GetTaskScheduler();
 | |
| 				SOCKET sockfd = conn->GetSocket();
 | |
| 				if (!scheduler->AddTriggerEvent([this, sockfd] {this->RemoveConnection(sockfd); })) {
 | |
| 					scheduler->AddTimer([this, sockfd]() {this->RemoveConnection(sockfd); return false; }, 100);
 | |
| 				}
 | |
| 			});
 | |
| 		}
 | |
| 	});
 | |
| }
 | |
| 
 | |
| TcpServer::~TcpServer()
 | |
| {
 | |
| 	Stop();
 | |
| }
 | |
| 
 | |
| bool TcpServer::Start(std::string ip, uint16_t port)
 | |
| {
 | |
| 	Stop();
 | |
| 
 | |
| 	if (!is_started_) {
 | |
| 		if (acceptor_->Listen(ip, port) < 0) {
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		port_ = port;
 | |
| 		ip_ = ip;
 | |
| 		is_started_ = true;
 | |
| 		return true;
 | |
| 	}
 | |
| 
 | |
| 	return false;
 | |
| }
 | |
| 
 | |
| void TcpServer::Stop()
 | |
| {
 | |
| 	if (is_started_) {		
 | |
| 		mutex_.lock();
 | |
| 		for (auto iter : connections_) {
 | |
| 			iter.second->Disconnect();
 | |
| 		}
 | |
| 		mutex_.unlock();
 | |
| 
 | |
| 		acceptor_->Close();
 | |
| 		is_started_ = false;
 | |
| 
 | |
| 		while (1) {
 | |
| 			Timer::Sleep(10);
 | |
| 			if (connections_.empty()) {
 | |
| 				break;
 | |
| 			}
 | |
| 		}
 | |
| 	}	
 | |
| }
 | |
| 
 | |
| TcpConnection::Ptr TcpServer::OnConnect(SOCKET sockfd)
 | |
| {
 | |
| 	return std::make_shared<TcpConnection>(event_loop_->GetTaskScheduler().get(), sockfd);
 | |
| }
 | |
| 
 | |
| void TcpServer::AddConnection(SOCKET sockfd, TcpConnection::Ptr tcpConn)
 | |
| {
 | |
| 	std::lock_guard<std::mutex> locker(mutex_);
 | |
| 	connections_.emplace(sockfd, tcpConn);
 | |
| }
 | |
| 
 | |
| void TcpServer::RemoveConnection(SOCKET sockfd)
 | |
| {
 | |
| 	std::lock_guard<std::mutex> locker(mutex_);
 | |
| 	connections_.erase(sockfd);
 | |
| }
 |