From 9c6ba70c4502f0f32b0389df79cd88a832198546 Mon Sep 17 00:00:00 2001 From: eric Date: Thu, 9 Jul 2020 02:30:27 +0800 Subject: [PATCH] add tcp client; test tcp server and client; --- CMakeLists.txt | 2 +- include/communicate/tcp_client.h | 45 +++++++++++++++++++++++++++++++ include/communicate/tcp_server.h | 5 ++-- include/debug_tools/print_tools.h | 8 +++--- src/communicate/CMakeLists.txt | 4 +-- src/communicate/tcp_client.cpp | 41 ++++++++++++++++++++++++++++ src/communicate/tcp_server.cpp | 23 +++++++++++++--- src/debug_tools/print_tools.cpp | 10 +++---- src/utils/CMakeLists.txt | 2 -- test/CMakeLists.txt | 1 + test/test_commu/CMakeLists.txt | 9 +++++++ test/test_commu/main.cpp | 31 +++++++++++++++++++++ test/test_util/CMakeLists.txt | 2 +- 13 files changed, 158 insertions(+), 25 deletions(-) create mode 100644 include/communicate/tcp_client.h create mode 100644 src/communicate/tcp_client.cpp create mode 100644 test/test_commu/CMakeLists.txt create mode 100644 test/test_commu/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 60d5931..9c6aa19 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ set(CMAKE_CXX_STANDARD 14) include_directories(include/) include_directories(utils/) -find_package(Boost REQUIRED) +find_package(Boost REQUIRED thread) find_package(OpenSSL 1.1.1 REQUIRED) include_directories(${Boost_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR} ${SQLiteCpp_INCLUDE_DIRS}) diff --git a/include/communicate/tcp_client.h b/include/communicate/tcp_client.h new file mode 100644 index 0000000..f081424 --- /dev/null +++ b/include/communicate/tcp_client.h @@ -0,0 +1,45 @@ +// +// Created by 胡宇 on 2020/7/9. +// + +#ifndef NET_TCP_CLIENT_H +#define NET_TCP_CLIENT_H + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +namespace Net { + + class TCPClient { + public: + TCPClient(const std::string &ip, int port); + + int sendData(const std::string &data); + + + private: + int fd{}; + struct sockaddr_in client_addr{}; + + std::stringstream recv_buff; + + void create_socket_and_connection(); + + void recv_cycle(); + + static void recv_data(TCPClient *client); + }; + +} + + +#endif //NET_TCP_CLIENT_H diff --git a/include/communicate/tcp_server.h b/include/communicate/tcp_server.h index ff732b1..90288bd 100644 --- a/include/communicate/tcp_server.h +++ b/include/communicate/tcp_server.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -43,7 +44,7 @@ namespace Net { int fd; int status = 0; struct sockaddr_in server_addr; - std::stringstream recv_buff; + std::queue recv_buff; boost::mutex buff_mutex; boost::thread *p_accept_manager_thread; @@ -51,7 +52,7 @@ namespace Net { static void accept_manager(TCPServer *server); - static void accept(int fd, boost::mutex *buff_mutex, std::stringstream *recv_buff, const int *status); + static void accept(int fd, boost::mutex *buff_mutex, std::queue *recv_buff, const int *status); void create_socket(int port); }; diff --git a/include/debug_tools/print_tools.h b/include/debug_tools/print_tools.h index bce018a..11e154f 100644 --- a/include/debug_tools/print_tools.h +++ b/include/debug_tools/print_tools.h @@ -19,13 +19,11 @@ namespace Net { using FormalItem = pair; - void printError(string error_info); + void debugPrintError(const string &error_info); - void printWarning(string warning_info); + void debugPrintWarning(const string &warning_info); - void printSuccess(string success_info); - - void printRed(string red_info); + void debugPrintSuccess(const string &success_info); void printInfo(const string& info, const string& tag); diff --git a/src/communicate/CMakeLists.txt b/src/communicate/CMakeLists.txt index 78a9530..aa67340 100644 --- a/src/communicate/CMakeLists.txt +++ b/src/communicate/CMakeLists.txt @@ -1,5 +1,3 @@ file(GLOB commuSrc *.cpp) -add_library(commu STATIC ${commuSrc}) - -target_link_libraries(commu utils debugTools) \ No newline at end of file +add_library(commu STATIC ${commuSrc}) \ No newline at end of file diff --git a/src/communicate/tcp_client.cpp b/src/communicate/tcp_client.cpp new file mode 100644 index 0000000..2f2053d --- /dev/null +++ b/src/communicate/tcp_client.cpp @@ -0,0 +1,41 @@ +// +// Created by 胡宇 on 2020/7/9. +// + +#include "communicate/tcp_client.h" + +void Net::TCPClient::recv_data(Net::TCPClient *client) { + u_char buff[1024]; + int len; + while ((len = recv(client->fd, buff, sizeof(buff), 0)) > 0) { + client->recv_buff.write(reinterpret_cast(buff), len); + } +} + +void Net::TCPClient::recv_cycle() { + boost::thread recv_thread(TCPClient::recv_data, + this); + recv_thread.detach(); +} + +void Net::TCPClient::create_socket_and_connection() { + if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { + throw std::runtime_error("create socket failed."); + } + connect(fd, (struct sockaddr *) &client_addr, sizeof(client_addr)); +} + +int Net::TCPClient::sendData(const std::string &data) { + create_socket_and_connection(); + recv_cycle(); + int len = send(fd, data.data(), data.size(), 0); + close(fd); + return len; +} + +Net::TCPClient::TCPClient(const std::string &ip, int port) { + std::memset(&client_addr, 0, sizeof(client_addr)); + client_addr.sin_family = AF_INET; + client_addr.sin_addr.s_addr = inet_addr(ip.c_str()); + client_addr.sin_port = htons(port); +} diff --git a/src/communicate/tcp_server.cpp b/src/communicate/tcp_server.cpp index 2e5feee..578fe72 100644 --- a/src/communicate/tcp_server.cpp +++ b/src/communicate/tcp_server.cpp @@ -2,17 +2,21 @@ // Created by 胡宇 on 2020/7/7. // +#include "debug_tools/print_tools.h" #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(); + accept_manager_thread.detach(); } void Net::TCPServer::accept_manager(Net::TCPServer *server) { + Net::PrintTools::debugPrintSuccess("AcceptManager Started."); while(true){ int connect_fd = ::accept(server->fd, nullptr, nullptr); + Net::PrintTools::debugPrintSuccess("New Connection."); + 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); @@ -21,19 +25,23 @@ void Net::TCPServer::accept_manager(Net::TCPServer *server) { } } -void Net::TCPServer::accept(int fd, boost::mutex *buff_mutex, std::stringstream *recv_buff, const int *status) { +void Net::TCPServer::accept(int fd, boost::mutex *buff_mutex, std::queue *recv_buff, const int *status) { + Net::PrintTools::debugPrintSuccess("Try Getting Data From Connection."); uint8_t buff[1024]; int len; std::vector accept_buff; while((len = recv(fd, buff, sizeof(buff), 0)) > 0 && *status == 0){ + Net::PrintTools::debugPrintSuccess("Received."); 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()); + for(unsigned char & i : accept_buff) + recv_buff->push(i); buff_mutex->unlock(); } close(fd); + Net::PrintTools::debugPrintSuccess("Connection Closed."); } void Net::TCPServer::create_socket(int port) { @@ -61,5 +69,12 @@ Net::TCPServer::TCPServer(int port, int max_connection) { } uint8_t Net::TCPServer::readByte() { - return recv_buff.get(); + uint8_t byte = '\0'; + buff_mutex.try_lock(); + if(!recv_buff.empty()) { + byte = recv_buff.front(); + recv_buff.pop(); + } + buff_mutex.unlock(); + return byte; } diff --git a/src/debug_tools/print_tools.cpp b/src/debug_tools/print_tools.cpp index a974def..dc46784 100644 --- a/src/debug_tools/print_tools.cpp +++ b/src/debug_tools/print_tools.cpp @@ -8,22 +8,18 @@ using std::string; namespace Net { namespace PrintTools { - void printError(const string &error_info) { + void debugPrintError(const string &error_info) { printf("\033[31mError: %s\033[0m\n", error_info.data()); } - void printWarning(const string &warning_info) { + void debugPrintWarning(const string &warning_info) { printf("\033[33mWarning: %s\033[0m\n", warning_info.data()); } - void printSuccess(const string &success_info) { + void debugPrintSuccess(const string &success_info) { printf("\033[32m%s\033[0m\n", success_info.data()); } - void printRed(const string &red_info) { - printf("\033[31m%s\n\033[0m", red_info.data()); - } - void printInfo(const string& info, const string& tag) { printf("[DEBUG INFO] %s ", info.data()); if(!tag.empty()) diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt index 0fd6aa0..d327464 100644 --- a/src/utils/CMakeLists.txt +++ b/src/utils/CMakeLists.txt @@ -1,5 +1,3 @@ file(GLOB utilSrc *.cpp) add_library(utils STATIC ${utilSrc}) - -target_link_libraries(utils debugTools ssl crypto) \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 65da75a..adb5254 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -6,3 +6,4 @@ set(GTEST_LIBS gtest gmock pthread dl) link_directories(${GTEST_LIB}) add_subdirectory(test_util) +add_subdirectory(test_commu) diff --git a/test/test_commu/CMakeLists.txt b/test/test_commu/CMakeLists.txt new file mode 100644 index 0000000..0634114 --- /dev/null +++ b/test/test_commu/CMakeLists.txt @@ -0,0 +1,9 @@ + +file(GLOB testSrc *.cpp) + +add_compile_definitions(DEBUG) + +add_executable(testCommu ${testSrc}) + +target_link_libraries(testCommu commu debugTools Boost::thread) + diff --git a/test/test_commu/main.cpp b/test/test_commu/main.cpp new file mode 100644 index 0000000..1d83182 --- /dev/null +++ b/test/test_commu/main.cpp @@ -0,0 +1,31 @@ +// +// Created by 胡宇 on 2020/7/9. +// + +#include +#include + +#include "debug_tools/print_tools.h" +#include "communicate/tcp_server.h" +#include "communicate/tcp_client.h" + +using namespace Net; + +int main(int argc, char *argv[]){ + if(fork() == 0) { + PrintTools::debugPrintSuccess("Child Started."); + TCPClient client("127.0.0.1", 9048); + for(int i = 0; i < 32; i++, usleep(1e4)) + client.sendData("Hello"); + PrintTools::debugPrintSuccess("Child Exited."); + } + else{ + PrintTools::debugPrintSuccess("Father Started."); + TCPServer server(9048, 100); + while (true){ + std::putchar(server.readByte()); + usleep(1e3); + } + } + return 0; +} \ No newline at end of file diff --git a/test/test_util/CMakeLists.txt b/test/test_util/CMakeLists.txt index 598a561..ffda1a7 100644 --- a/test/test_util/CMakeLists.txt +++ b/test/test_util/CMakeLists.txt @@ -5,7 +5,7 @@ add_executable(testUtils ${testSrc}) message(${GTEST_LIBS}) -target_link_libraries(testUtils utils debugTools ${GTEST_LIBS}) +target_link_libraries(testUtils utils debugTools ssl crypto ${GTEST_LIBS}) add_test(Name testUtils COMMAND testUtils) \ No newline at end of file