介绍
下面的程序实现了对 TCP 连接的分流,即将一个 TCP 连接的流量分布到多个 TCP 连接上进行传输。
本程序的主要作用是在特定网络环境下提升通过 TCP 连接的 OpenVPN 服务的速率,使之充分利用带宽。
程序的主要复杂之处在于单生产者—多消费者、多生产者—单消费者两种同步方式的实现。
代码
// multisocks, copyright (c) 2013 coolypf #include <stdio.h> #include <stdlib.h> #include <string.h> #include <string> #include <map> #include <vector> #include <Poco/Thread.h> #include <Poco/Event.h> #include <Poco/ErrorHandler.h> #include <Poco/FIFOBuffer.h> #include <Poco/Net/StreamSocket.h> #include <Poco/Net/ServerSocket.h> using namespace std; using namespace Poco; using namespace Poco::Net; class error_handler : public ErrorHandler { public: virtual void exception(const Exception& exc) { printf("[!] Thread %u: Caught exception: %s\n", (unsigned int)Thread::currentTid(), exc.displayText().c_str()); fflush(stdout); exit(1); } virtual void exception(const std::exception& exc) { printf("[!] Thread %u: Caught exception: %s\n", (unsigned int)Thread::currentTid(), exc.what()); fflush(stdout); exit(2); } virtual void exception() { printf("[!] Thread %u: Caught unknown exception\n", (unsigned int)Thread::currentTid()); fflush(stdout); exit(3); } }; class { map<string, string> config; string empty; int read_file(const char *filename, vector<char> &out) { FILE *fp = fopen(filename, "rb"); if (!fp) { printf("[!] Fail to load: %s\n", filename); return 1; } char buf[4096]; size_t sz; while ((sz = fread(buf, 1, 4096, fp))) out.insert(out.end(), buf, buf + sz); fclose(fp); for (size_t i = 0; i < out.size(); ++i) if (!out[i]) out[i] = ' '; return 0; } void split_lines(const vector<char> &in, vector<string> &out) { size_t pos = 0; for (size_t i = 0; i < in.size(); ++i) { if (in[i] != '\r' && in[i] != '\n') continue; out.push_back(string(in.begin() + pos, in.begin() + i)); if (in[i] == '\r' && i + 1 < in.size() && in[i + 1] == '\n') i++; pos = i + 1; } if (pos < in.size()) out.push_back(string(in.begin() + pos, in.end())); } void trim_string(string &str) { const char *spaces = " \r\n\t\xb\xc"; int first = 0, last = (int)str.size() - 1; while (first <= last && strchr(spaces, str[first])) ++first; while (last >= first && strchr(spaces, str[last])) --last; str.resize(last + 1); str.erase(0, first); } void split_string(const string &in, vector<string> &out, const char *delims) { size_t pos = 0; for (size_t i = 0; i < in.size(); ++i) { if (!strchr(delims, in[i])) continue; string part(in.begin() + pos, in.begin() + i); trim_string(part); out.push_back(part); pos = i + 1; } { string part(in.begin() + pos, in.end()); trim_string(part); out.push_back(part); } } public: int load(const char *filename) { vector<char> content; if (read_file(filename, content)) return 1; vector<string> lines; split_lines(content, lines); for (size_t i = 0; i < lines.size(); ++i) { if (lines[i].empty() || lines[i][0] == '#') continue; vector<string> parts; split_string(lines[i], parts, "="); if (parts.size() != 2 || parts[0].empty())