/** Created by crupest. * This is the server program. */ #include "Common.h" #include "Output.h" #include "fmt/core.h" #include #include #include #include #include #ifdef WIN32 #include #include #else #include #include #include #endif const auto bind_address = "127.0.0.1"; // control bind address const u_short port = 1234; // control bind port struct Connection { std::thread thread; int socket; sockaddr_in address; String address_string; String name; folly::ProducerConsumerQueue send_queue{100}; folly::CancellationSource cancellation_source; }; void ResponseThreadProc(Connection *connection) { auto host = ConvertCharString(inet_ntoa(connection->address.sin_addr)); auto port = htons(connection->address.sin_port); connection->address_string = fmt::format(CRUT("{}:{}"), host, port); std::string rest; std::string n = SafeReadUntil(connection->socket, '\n', rest); connection->name = ConvertCharString(n); SendOutput(CRUT("Connected to {}, whose name is {}."), connection->address_string, connection->name); std::thread revieve_thread( [](Connection *connection) { std::string rest; while (true) { if (connection->cancellation_source.isCancellationRequested()) { break; } std::string s = SafeReadUntil(connection->socket, '\n', rest); SendOutput(CRUT("{}({}) send a message:\n{}\n"), connection->name, connection->address_string, ConvertCharString(s)); } }, connection); while (true) { if (connection->cancellation_source.isCancellationRequested()) { break; } std::string s; if (connection->send_queue.read(s)) { SafeSend(connection->socket, s); } } CloseSocket(connection->socket); } int Main() { std::vector connections; int server_socket; if ((server_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1) { PrintErrorMessageAndExit(CRUT("Failed to create socket.")); } sockaddr_in server_address; server_address.sin_family = AF_INET; server_address.sin_port = htons(port); server_address.sin_addr.s_addr = inet_addr(bind_address); memset(&(server_address.sin_zero), 0, sizeof(server_address.sin_zero)); if (bind(server_socket, reinterpret_cast(&server_address), sizeof(sockaddr_in)) == -1) { PrintErrorMessageAndExit(CRUT("Failed to bind.")); } if (listen(server_socket, SOMAXCONN) == -1) { PrintErrorMessageAndExit(CRUT("Failed to listen.")); } SendOutput(OutputColor::Green, CRUT("Now start to accept incoming connection.\n")); while (true) { sockaddr_in client_address; int client_socket; unsigned sin_size = sizeof(sockaddr_in); client_socket = accept(server_socket, reinterpret_cast(&client_address), #ifdef WIN32 reinterpret_cast #endif (&sin_size)); if (client_socket == -1) { PrintErrorMessageAndExit(CRUT("Failed to accecpt.")); } Connection connection; connection.socket = client_socket; connection.address = client_address; connections.push_back(std::move(connection)); connection.thread = std::thread(ResponseThreadProc, &connections.back()); connection.thread.detach(); } }