https://github.com/bakwc/udt-nat-traverse
Example of nat traversal using udt library. UDT is a udp based connection establishing protocol.
#include <arpa/inet.h> #include <udt.h> #include <iostream> #include <cstring> using namespace std; int main() { UDTSOCKET serv = UDT::socket(AF_INET, SOCK_STREAM, 0); sockaddr_in my_addr; my_addr.sin_family = AF_INET; my_addr.sin_port = htons(6890); my_addr.sin_addr.s_addr = INADDR_ANY; memset(&(my_addr.sin_zero), '\0', 8); if (UDT::ERROR == UDT::bind(serv, (sockaddr*)&my_addr, sizeof(my_addr))) { cout << "bind error: " << UDT::getlasterror().getErrorMessage(); return 0; } UDT::listen(serv, 10); while(true) { int namelen; sockaddr_in recver1addr, recver2addr; char ip[16]; char data[6]; cout << "waiting for connections\n"; UDTSOCKET recver1 = UDT::accept(serv, (sockaddr*)&recver1addr, &namelen); cout << "new connection: " << inet_ntoa(recver1addr.sin_addr) << ":" << ntohs(recver1addr.sin_port) << endl; UDTSOCKET recver2 = UDT::accept(serv, (sockaddr*)&recver2addr, &namelen); cout << "new connection: " << inet_ntoa(recver2addr.sin_addr) << ":" << ntohs(recver2addr.sin_port) << endl; cout << "sending addresses\n"; *(uint32_t*)data = recver2addr.sin_addr.s_addr; *(uint16_t*)(data + 4) = recver2addr.sin_port; UDT::send(recver1, data, 6, 0); *(uint32_t*)data = recver1addr.sin_addr.s_addr; *(uint16_t*)(data + 4) = recver1addr.sin_port; UDT::send(recver2, data, 6, 0); UDT::close(recver1); UDT::close(recver2); } UDT::close(serv); return 1; }
#include <iostream> #include <udt.h> #include <arpa/inet.h> #include <cstring> #include <ctime> #include <cstdlib> #include <unistd.h> using namespace std; using namespace UDT; int main() { UDTSOCKET client = UDT::socket(AF_INET, SOCK_STREAM, 0); sockaddr_in serv_addr; serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(6890); inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr); // server address here memset(&(serv_addr.sin_zero), '\0', 8); // selecting random local port srand(time(NULL)); int myPort = 9001 + rand() % 200; printf("my port: %d\n", myPort); sockaddr_in my_addr; my_addr.sin_family = AF_INET; my_addr.sin_port = htons(myPort); my_addr.sin_addr.s_addr = INADDR_ANY; memset(&(my_addr.sin_zero), '\0', 8); // Connecting to server // binding my port if (UDT::ERROR == UDT::bind(client, (sockaddr*)&my_addr, sizeof(my_addr))) { cout << "bind error: " << UDT::getlasterror().getErrorMessage(); return 0; } // connect to the server if (UDT::ERROR == UDT::connect(client, (sockaddr*)&serv_addr, sizeof(serv_addr))) { cout << "connect error: " << UDT::getlasterror().getErrorMessage(); return 42; } char data[6]; if (UDT::ERROR == UDT::recv(client, data, 6, 0)) { cout << "recv error:" << UDT::getlasterror().getErrorMessage() << endl; return 0; } sockaddr_in peer_addr; peer_addr.sin_family = AF_INET; peer_addr.sin_addr.s_addr = *(uint32_t*)data; peer_addr.sin_port = *(uint16_t*)(data + 4); cout << "addr received: " << inet_ntoa(peer_addr.sin_addr) << ":" << ntohs(peer_addr.sin_port) << endl; UDT::close(client); client = UDT::socket(AF_INET, SOCK_STREAM, 0); bool rendezvous = true; UDT::setsockopt(client, 0, UDT_RENDEZVOUS, &rendezvous, sizeof(bool)); if (UDT::ERROR == UDT::bind(client, (sockaddr*)&my_addr, sizeof(my_addr))) { cout << "bind error: " << UDT::getlasterror().getErrorMessage(); return 0; } if (UDT::ERROR == UDT::connect(client, (sockaddr*)&peer_addr, sizeof(peer_addr))) { cout << "connect error: " << UDT::getlasterror().getErrorMessage(); return 42; } cout << "SUCCESS!\n"; sleep(2); // give another client time to connect too return 1; }