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); | ||
|  | } |