#include <cstdio> #include <cstdlib> #include <ctime> #include <cstdint> #include <thread> #define _ToString(x) #x #define ToString(x) _ToString(x) #define Line ToString(__LINE__) #if (_WIN32 || _WIN64) #include <WinSock2.h> #include <WS2tcpip.h> #include <dos.h> #pragma comment(lib, "ws2_32.lib") #pragma comment(lib, "User32.lib") #define _CRT_SECURE_NO_WARNINGS #pragma warning(disable : 4996) #define CloseSocket closesocket #define err(status, ...)\ {\ fprintf(stderr, __VA_ARGS__);\ exit(status);\ } #else #include <err.h> #define CloseSocket close #endif static uint64_t recvCount, sendCount; inline void SleepSeconds(uint32_t seconds) { #if (_WIN32 || _WIN64) Sleep(seconds * 1000); #else sleep(seconds); #endif } void TimePrinter() { time_t t = time(NULL); struct tm* lt = localtime(&t); fflush(stdout); printf("[ %d-%d-%d %d:%d:%d ] ", lt->tm_year + 1900, lt->tm_mon + 1, lt->tm_mday, lt->tm_hour, lt->tm_min, lt->tm_sec); } void Transfer(SOCKET sock1, SOCKET sock2, bool isRecv = true) { char buf[4096] = { 0 }; int len; while ((len = recv(sock1, buf, 4096, 0)) > 0) { send(sock2, buf, len, 0); if (isRecv) recvCount += len; else sendCount += len; } } int main(int argc, char* argv[]) { if (argc != 4) err(EXIT_FAILURE, "Usage:\n %s ServerIp ServerPort ClientPort.\n", argv[0]); const char* serverIp = argv[1]; const char* serverPort = argv[2]; const char* clientPort = argv[3]; TimePrinter(); printf("init...\n"); #if (_WIN32 || _WIN64) WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) < 0) err(EXIT_FAILURE, Line ":WinSock init fail"); #else struct sigaction action; action.sa_handler = [](int) {}; sigemptyset(&action.sa_mask); action.sa_flags = 0; sigaction(SIGPIPE, &action, nullptr); #endif struct addrinfo hints; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; std::thread logThread([]() { while (true) { fflush(stdout); printf("recv:%.fkB - send:%.fkB\r\033[k", round(recvCount / 1024.), round(sendCount / 1024.)); SleepSeconds(1); } }); while (true) { try { TimePrinter(); printf("Link start...\n"); struct addrinfo* serverAddr; if (getaddrinfo(serverIp, serverPort, &hints, &serverAddr) != 0) err(EXIT_FAILURE, Line ":(server)getaddrinfo(%s,%s) failed.\n", serverIp, serverPort); SOCKET serverSock = socket(serverAddr->ai_family, serverAddr->ai_socktype, serverAddr->ai_protocol); if (serverSock <= 0) err(EXIT_FAILURE, Line":(server)Can't open socket"); struct addrinfo* clientAddr; if (getaddrinfo("localhost", clientPort, &hints, &clientAddr) != 0) err(EXIT_FAILURE, Line ":(client)getaddrinfo(%s,%s) failed.\n", "localhost", clientPort); SOCKET clientSock = socket(clientAddr->ai_family, clientAddr->ai_socktype, clientAddr->ai_protocol); if (clientSock <= 0) err(EXIT_FAILURE, Line":(server)Can't open socket"); if (connect(serverSock, serverAddr->ai_addr, serverAddr->ai_addrlen) != 0) { perror(Line ":(server)connect() failed."); CloseSocket(serverSock); SleepSeconds(1); continue; } if (connect(clientSock, clientAddr->ai_addr, clientAddr->ai_addrlen) != 0) { perror(Line ":(client)connect() failed."); CloseSocket(clientSock); SleepSeconds(1); continue; } std::thread thread1(Transfer, clientSock, serverSock, false); std::thread thread2(Transfer, serverSock, clientSock, true); thread2.join(); CloseSocket(clientSock); CloseSocket(serverSock); } catch (std::exception& e) { perror(e.what()); } } }