TCP over the internet

Previous topic - Next topic

MrTAToad

I'm trying to connect a computer over the internet with the following :

Code (glbasic) Select
GLOBAL gSession$="myTest"
GLOBAL ip$,socket%,rv%,msg$,port%=21790
LOCAL a$

INPUT a$,0,0
IF a$="H" THEN AnnounceSessionINET(TRUE)

ip$=FindSessionINET$()
IF ip$=""
IF AnnounceSessionINET(FALSE)
DEBUG "Hosted"
ELSE
DEBUG "Not hosted"
ENDIF

IF SOCK_INIT()
socket%=SOCK_TCPLISTEN(port%)
SOCK_SETBLOCKING socket%,FALSE
IF socket%>=0
WHILE TRUE
rv%=SOCK_RECV(socket%,msg$,1024)
PRINT "Message : "+msg$,0,0
SHOWSCREEN
WEND
ELSE
PRINT "Socket error",0,0; SHOWSCREEN; KEYWAIT
ENDIF
ELSE
ENDIF

ELSE
PRINT "IP : "+ip$,0,0; SHOWSCREEN; KEYWAIT
IF SOCK_INIT()
socket%=SOCK_TCPCONNECT(ip$,port%)
IF socket%>=0
WHILE TRUE
IF KEY(28)
IF SOCK_TCPSEND(port%,"This is a test")<0
PRINT "Error : "+NETGETLASTERROR$(),0,0; SHOWSCREEN; KEYWAIT
ELSE
PRINT "Sent",0,0
ENDIF
ENDIF

SHOWSCREEN
WEND
ELSE
PRINT "Socket error :"+NETGETLASTERROR$(),0,0; SHOWSCREEN; KEYWAIT
ENDIF
ENDIF
ENDIF
END

FUNCTION FindSessionINET$:
LOCAL ip$
// see if there is already a session
ip$ = NETWEBGET$("www.glbasic.com", "/netsession.php?session="+gSession$+"&host=0", 0, 256)

IF LEN(ip$)>4 THEN RETURN ip$
RETURN ""
ENDFUNCTION


// Announce session in INET
// true/false
FUNCTION AnnounceSessionINET%: bClose%
LOCAL ip$
IF bClose% = FALSE
ip$ = NETWEBGET$("www.glbasic.com", "/netsession.php?session="+gSession$+"&host=1", 0, 256)
IF ip$="HOSTED" THEN RETURN TRUE
RETURN FALSE
ELSE
// tell the server to stop it
NETWEBGET$("www.glbasic.com", "/netsession.php?session="+gSession$+"&host=-1", 0, 256)
RETURN TRUE
ENDIF
ENDFUNCTION


Hosting is okay, but when the computer attemps to join, the socket connect returns an error of "a blocking error is currently executing".

I am currently using the latest beta.

It is quite possible that (as has been discussed a while ago now) port forwarding is needed - unfortunately until I get a new router at the end of next week, I can't verify that.

mentalthink

Yes MrT I try this a lot of time, and I never contact whit the other computer... I think perhaps it's something whit ports... Really I don't know too much about networks...

dreamerman

If server and client aren't in same local network, then port forwarding on server side is always needed. Of course if you are not using some VPN software that could bypass that issue.
You should also remember to add your app (on host system) to firewall excludes, or just ports range that app is using.
Check my source code editor for GLBasic - link Update: 20.04.2020

MrTAToad

#3
Yes - finally got it working over the internet!  Worked out how to do port forwarding at last!

Moru

There is no need to do port forwarding or open up ports in most routers if you use UDP hole-punching. The only thing you need to do is one of the computers needs to know the others IP-number and start sending packets. The other one just sends packets "somewhere" as long as it's the same port number. Suddenly the packets from the first computer will go thru to the second computer.

If one computer is using a certain port for sending, the router opens up a tunnel back to that computer for incoming packets. Some routers demands that you send to the same IP-number as you recieve from but most don't even bother checking this.

erico

Super naive questions as I´m interested but don´t know jack s´´t about... :-[

So the programs can share variables?

Is that the way this works?
So in one program you code as expecting to receive those variables value back? Like you code a server/terminal in one program and deal that?

MrTAToad

Do you have any UDP tunnelling code anywhere ?

Robert

I have a client and server program and it works but when it has been inactive for a while the connection is broken. Is that internet or program dependent? 

Moru

I think most routers will kill an inactive connection. Send a message now and then to keep it alive.

Moru

Quote from: MrTAToad on 2013-Mar-28
Do you have any UDP tunnelling code anywhere ?

I thought I had but that wiki is down. But really, it's just that simple. Send UDP to other client. Send UDP back. The second or third attempt will go through the router just fine. (Not the first attempt, that will get blocked until both have send one packet each).

You also have to make sure you keep the connection alive by sending a packet every few seconds. Times are different depending on router so might need some research.

My testcode, not tested for years:

Code (glbasic) Select
// --------------------------------- //
// Project: NetUDPThruRouter
// Start: Tuesday, September 15, 2009
// IDE Version: 7.104

// Works if you send a message from inside the firewall to the outside IP of the other client
// And then send a message from that client on the outside of the firewall to the inside.
// Both clients can be behind a firewall.


GLOBAL sock%               // The socket connection
GLOBAL port% = 15000       // Port number to use

LOCAL ok%, ip%, rv%, msg$
LOCAL myip$
LOCAL destip$
LOCAL timeout
LOCAL src_ip%, src_port% // The ip-address and port of the last packet

myip$ = NETGETIP$()        // Get our local IP just for the show
log("Our IP: "+ myip$)

STDOUT "\nDestination IP: "
destip$ = STDIN$()
// Just for less typing when testing
IF destip$ = "" THEN destip$ = "10.10.0.11"

ok = SOCK_INIT()    // Init network
IF ok
    sock = SOCK_UDPOPEN(port)    // Get the socket so we can send/recieve on the port
    IF sock <> -1
SOCK_SETBLOCKING sock, FALSE // Set socket to blocking(true), wait until message was sent or recieved

        ip = SOCK_GETIP(destip$) // Convert the string to an integer IP
        // Send 32 packets, waiting one second for an answer between each send
        FOR n = 0 TO 31
            log("Sending message: "+"Hello from "+myip$+" To: "+destip$)
            ok = SOCK_UDPSEND(sock, "Hello from "+myip$, ip, port)
            IF ok <> -1
                log("message sent with "+ok+" bytes")
                timeout = GETTIMERALL() + 1000      // Start timer for one second
                WHILE rv <> -1 AND GETTIMERALL() < timeout
                    rv = SOCK_RECV(sock, msg$, 999)
src_ip = SOCK_GETREMOTEIP(sock)
src_port = SOCK_GETREMOTEPORT(sock)
                    IF rv>0 THEN log("message recieved: ["+src_ip+"]["+src_port+"]["+msg$+"]")
                    IF rv=-1
                        log(NETGETLASTERROR$())     // Didn't work, tell user why
                        SOCK_CLOSE(sock)
                    ENDIF
                WEND
            ELSE
                log(NETGETLASTERROR$())
            ENDIF
        NEXT
    ELSE
        log(NETGETLASTERROR$())
    ENDIF
ELSE
    log(NETGETLASTERROR$())
ENDIF
KEYWAIT



FUNCTION log: str$
    STDOUT "\n"+str$
ENDFUNCTION

MrTAToad

Last time I tried it it, it didn't quite work.  That was with an earlier version of GLBasic, so I'll have to try again :)

Moru

I wrote it with version 7.1 and it worked fine last time I tried it. But as I said, this works on *most* routers. Not all :-)
Quake 2 was using something similar to this and that worked fine already then.
The linux guys were very surprised when their painstakingly secured firewall suddenly just let through traffic from outside of the network into the quake 2 server :-)

The example is not totally failsafe, you have to set it up and start it at the same time to see the effect so best is to use a remote control like Teamviewer to controll the other side so you see that something actually happens. And both endpoints can be behind a residential firewall.