Forum > Networking and Web Programming

[SOLVED] Hole punching - Step by Step - with simple example

(1/5) > >>

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

Go to full version