https://github.com/bakwc/udt-nat-traverse
Example of nat traversal using udt library. UDT is a udp based connection establishing protocol.
- server.cpp - waiting for two clients, send them their addresses
- client.cpp - connects to server, wait for other client address, connects to other client
#include <arpa/inet.h>
#include <udt.h>
#include <iostream>
#include <cstring> using namespace std; int main() {
UDTSOCKET serv = UDT::socket(AF_INET, SOCK_STREAM, ); sockaddr_in my_addr;
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons();
my_addr.sin_addr.s_addr = INADDR_ANY;
memset(&(my_addr.sin_zero), '\0', ); if (UDT::ERROR == UDT::bind(serv, (sockaddr*)&my_addr, sizeof(my_addr))) {
cout << "bind error: " << UDT::getlasterror().getErrorMessage();
return ;
} UDT::listen(serv, ); while(true) {
int namelen;
sockaddr_in recver1addr, recver2addr;
char ip[];
char data[];
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 + ) = recver2addr.sin_port;
UDT::send(recver1, data, , ); *(uint32_t*)data = recver1addr.sin_addr.s_addr;
*(uint16_t*)(data + ) = recver1addr.sin_port;
UDT::send(recver2, data, , ); UDT::close(recver1);
UDT::close(recver2);
} UDT::close(serv); return ;
}
#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, ); sockaddr_in serv_addr;
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons();
inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr); // server address here
memset(&(serv_addr.sin_zero), '\0', ); // selecting random local port
srand(time(NULL));
int myPort = + rand() % ;
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', ); // 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 ;
} // connect to the server
if (UDT::ERROR == UDT::connect(client, (sockaddr*)&serv_addr, sizeof(serv_addr))) {
cout << "connect error: " << UDT::getlasterror().getErrorMessage();
return ;
} char data[];
if (UDT::ERROR == UDT::recv(client, data, , )) {
cout << "recv error:" << UDT::getlasterror().getErrorMessage() << endl;
return ;
} 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 + ); 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, );
bool rendezvous = true;
UDT::setsockopt(client, , UDT_RENDEZVOUS, &rendezvous, sizeof(bool)); if (UDT::ERROR == UDT::bind(client, (sockaddr*)&my_addr, sizeof(my_addr))) {
cout << "bind error: " << UDT::getlasterror().getErrorMessage();
return ;
} if (UDT::ERROR == UDT::connect(client, (sockaddr*)&peer_addr, sizeof(peer_addr))) {
cout << "connect error: " << UDT::getlasterror().getErrorMessage();
return ;
}
cout << "SUCCESS!\n";
sleep(); // give another client time to connect too return ;
}