Forum > Networking and Web Programming
[SOLVED] Hole punching - Step by Step - with simple example
Key-Real:
I managed to setup the first Step:
I have a UDP server which accepts a client connection and now I knew the IP and Port of the clients.
What is the second Step?
nummer8:
In this thread hole punching is part of the discussion
https://forum.lazarus.freepascal.org/index.php/topic,52110.0.html
Key-Real:
I'm on the last step:
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} --- {$MODE OBJFPC}uses cthreads, Classes, blcksock, sockets, Synautil, SysUtils, nettools; var soket : TUDPBlockSocket; clientNumer : string; buf : TcharArray; s : string; bytesReceived : longint; remoteIP, remotePort : string; Type TreadThread = class(TThread) protected procedure Execute; override; public soket : TUDPBlockSocket; Constructor Create(CreateSuspended : boolean); end; TwriteThread = class(TThread) protected procedure Execute; override; public soket : TUDPBlockSocket; Constructor Create(CreateSuspended : boolean); end; constructor TreadThread.Create(CreateSuspended : boolean);begin inherited Create(CreateSuspended); FreeOnTerminate := True;end; procedure TreadThread.Execute;var buf : TcharArray;begin while (not Terminated) do begin bytesReceived:= soket.recvBuffer(PChar(@buf), sizeof(TcharArray)); checkError(soket); writeln(buf); sleep(100); end;end; constructor TwriteThread.Create(CreateSuspended : boolean);begin inherited Create(CreateSuspended); FreeOnTerminate := True;end; procedure TwriteThread.Execute;var buf : TcharArray; s : String;begin while (not Terminated) do begin s:= '->' + clientNumer; buf:= s; soket.SendBuffer(PChar(@buf[0]), length(s)); checkError(soket, 'write'); sleep(100); end;end; var readThread : TreadThread; writeThread : TwriteThread; begin soket:= TUDPBlockSocket.Create; soket.bind('0.0.0.0', '9090'); soket.SetRemoteSin(remoteServerIP, '1500'); checkError(soket); clientNumer:= '1'; if paramcount = 1 then clientNumer:= paramstr(1); buf[0]:= char(strtoint(clientNumer)); soket.SendBuffer(PChar(@buf[0]), 1); sleep(10); soket.Free; soket := TUDPBlockSocket.Create; soket.CreateSocket; soket.bind('0.0.0.0', '9090'); checkError(soket); while True do begin bytesReceived:= soket.recvBuffer(PChar(@buf), sizeof(buf)); if buf[0] = #3 then begin writeln('Handshake!'); break; end; end; soket.CloseSocket; soket.Free; s:=transcriptBuf2String(buf, 2, bytesReceived - 1); s:=copy(s, pos('@', s) + 1, length(s)); remoteIP:=copy(s, 0, pos(':', s) - 1); remotePort:=copy(s, pos(':', s) + 1, length(s)); writeln('other clinet is @', remoteIP, ':', remotePort, '!'); //// At this point I have correct IP and Port of the other Client!!!!!!!//// //// now I'm trying to connect and read/write... nothing happens :( why?// Soket:= TUDPBlockSocket.Create; Soket.CreateSocket; Soket.bind('0.0.0.0', '9090'); checkError(Soket, 'bind'); Soket.Connect(remoteIP, remotePort); checkError(Soket, 'connect'); readThread:=TreadThread.Create(false); readThread.soket:=soket; readThread.Start; writeThread:= TwriteThread.Create(false); writeThread.soket:=soket; writeThread.Start; readln; Soket.CloseSocket; Soket.Free;end.
I think I'm connecting wrong. How to establish connection?
Key-Real:
don't think I haven't look at the discussion at
https://forum.lazarus.freepascal.org/index.php/topic,52110.45.html
they tell just do
a socket.connect(remoteIP, remotePort);
this doesn't work :(
pls help
Warfley:
The important part about hole punching is that you need a two way handshake. Basically when you punch the initial hole, the router registers it with a target address, so when then a package comes for that port, that is not from that target address, it will be ignored by the router.
So what you need to do is after punching the first hole, is to then punch the same hole for the new target.
This could look like this:
--- Code: Text [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---[Alice] [Server] [Bob] | | | +--register(alice)-->| | | | | | |<--request(alice)-+ | | | |<-----addr(Bob)-----+---addr(alice)--->| | | +------------------punch--------------->| |<-----------------punch----------------+ | | |<--------------Communicate------------>|
The "punch" here is just an UDP message whose contents does not matter (it may or may not be blocked by the nat, depending if the punch of the other party has been successful first).
Communication is only possible after both punches went through their respective nat.
It's important that for all operations you always use the same private network port. So you always bind your socket to a fixed port, this way it's ensured that you can reuse the same output port.
Navigation
[0] Message Index
[#] Next page