diff --git a/include/communicate/tcp_server.h b/include/communicate/tcp_server.h index 7a25365..ff732b1 100644 --- a/include/communicate/tcp_server.h +++ b/include/communicate/tcp_server.h @@ -5,10 +5,55 @@ #ifndef NET_TCP_SERVER_H #define NET_TCP_SERVER_H +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + + namespace Net { class TCPServer { + public: + TCPServer(int port, int max_connection); + ~TCPServer(){ + stop(); + close(fd); + } + + void stop(){ + if(p_accept_manager_thread != nullptr) + p_accept_manager_thread->interrupt(); + this->status = -1; + } + + uint8_t readByte(); + + private: + int fd; + int status = 0; + struct sockaddr_in server_addr; + std::stringstream recv_buff; + boost::mutex buff_mutex; + boost::thread *p_accept_manager_thread; + + void cycle(); + + static void accept_manager(TCPServer *server); + + static void accept(int fd, boost::mutex *buff_mutex, std::stringstream *recv_buff, const int *status); + + void create_socket(int port); }; } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4f991e6..f508e42 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,2 +1,3 @@ add_subdirectory(utils) -add_subdirectory(debug_tools) \ No newline at end of file +add_subdirectory(debug_tools) +add_subdirectory(communicate) \ No newline at end of file diff --git a/src/communicate/tcp_server.cpp b/src/communicate/tcp_server.cpp index 7dc2ca8..2e5feee 100644 --- a/src/communicate/tcp_server.cpp +++ b/src/communicate/tcp_server.cpp @@ -3,3 +3,63 @@ // #include "communicate/tcp_server.h" + +void Net::TCPServer::cycle() { + boost::thread accept_manager_thread(TCPServer::accept_manager, this); + this->p_accept_manager_thread = &accept_manager_thread; + accept_manager_thread.join(); +} + +void Net::TCPServer::accept_manager(Net::TCPServer *server) { + while(true){ + int connect_fd = ::accept(server->fd, nullptr, nullptr); + if(connect_fd == -1) throw std::runtime_error("accept tcp connection error"); + else{ + boost::thread accept_thread(TCPServer::accept, connect_fd, &server->buff_mutex, &server->recv_buff, &server->status); + accept_thread.detach(); + } + } +} + +void Net::TCPServer::accept(int fd, boost::mutex *buff_mutex, std::stringstream *recv_buff, const int *status) { + uint8_t buff[1024]; + int len; + std::vector accept_buff; + while((len = recv(fd, buff, sizeof(buff), 0)) > 0 && *status == 0){ + for(int i = 0; i < len; ++i) accept_buff.push_back(buff[i]); + } + if(*status == 0) { + buff_mutex->lock(); + recv_buff->write(reinterpret_cast(accept_buff.data()), accept_buff.size()); + buff_mutex->unlock(); + } + close(fd); +} + +void Net::TCPServer::create_socket(int port) { + fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if(!~fd) throw std::runtime_error("could not create socket file."); + + std::memset(&server_addr, 0, sizeof(struct sockaddr_in)); + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = htonl(INADDR_ANY); + server_addr.sin_port = htons(port); +} + +Net::TCPServer::TCPServer(int port, int max_connection) { + + create_socket(port); + + if(bind(fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) == -1) + throw std::runtime_error("bind port failed."); + + if(listen(fd, max_connection) == -1) + throw std::runtime_error("listen socket failed."); + + + cycle(); +} + +uint8_t Net::TCPServer::readByte() { + return recv_buff.get(); +}