QB64.org Forum

Active Forums => Programs => Topic started by: SMcNeill on November 18, 2019, 12:06:06 pm

Title: Mini Messenger
Post by: SMcNeill on November 18, 2019, 12:06:06 pm
A lot of folks are curious about how we can get our programs to talk to each other, and curious about how we'd use QB64 to communicate via TCP/IP over a network.  The wiki has a few examples, but they tend to be outdated and simply don't work for me.  (Such as the mini-messenger  example here: http://www.qb64.org/wiki/OPENHOST.) I figured people might like a working example of how to get all the proper parts working together, so I tried various wiki samples and eventually decided to rework one until I got it to working for me...

The finished code here is working as intended on Windows. (I dunno if it'll work for Linux or Mac users, but I'd love to hear if it does or doesn't.)  Instead of a single set of code which tries to toggle between client and host, I worked this up as two separate sets of code -- one for each.   Copy one set of code into QB64, and then run it.  Then, while that program is still running in the background, copy the second set of code and run it..  Type in either program and watch as they happily communicate with each other without any issues.

THE HOST:
Code: QB64: [Select]
  1. DIM SHARED Users(1 TO 1000) ' array to hold other client info
  2. DIM SHARED NumClients
  3.  
  4.  
  5. PRINT "[Steve's Mini Messenger]"
  6. host = _OPENHOST("TCP/IP:7319") ' no host found, so begin new host
  7. IF host THEN
  8.     PRINT "[Beginning new host chat session!]"
  9.     NumClients = 0
  10.     client = _OPENCLIENT("TCP/IP:7319:localhost")
  11.     IF client = 0 THEN PRINT "ERROR: could not attach host's personal client to host!"
  12.     INPUT "Enter your name:", myname$
  13.     'PRINT #client, myname$ + " connected!"
  14.     PRINT "[Chat session active!]"
  15.     PRINT "ERROR: Could not begin new host!"
  16. END IF ' host
  17.  
  18.  
  19. DO ' host main loop
  20.     newclient = _OPENCONNECTION(host) ' receive any new connection
  21.     IF newclient THEN
  22.         NumClients = NumClients + 1
  23.         Users(NumClients) = newclient
  24.         PRINT "Welcome to Steve's Mini Messenger!"
  25.     END IF
  26.     FOR i = 1 TO NumClients
  27.         GetMessage Users(i) 'check all clients for a message
  28.         IF out$ <> "" THEN
  29.             l = LEN(out$)
  30.             FOR j = 1 TO NumClients ' distribute incoming messages to all clients
  31.                 PUT #Users(j), , l
  32.                 PUT #Users(j), , out$
  33.             NEXT
  34.         END IF
  35.     NEXT i
  36.  
  37.     SendMessage myname$, mymessage$, client
  38.     _LIMIT 30
  39.  
  40.  
  41. SUB GetMessage (client) ' get & display any new message
  42.     GET #client, , l
  43.     IF l > 0 THEN
  44.         out$ = SPACE$(l)
  45.         GET #client, , out$
  46.         VIEW PRINT 1 TO 20
  47.         LOCATE 20, 1
  48.         PRINT out$
  49.         VIEW PRINT 1 TO 24
  50.     ELSE
  51.         out$ = ""
  52.     END IF
  53.  
  54. SUB SendMessage (myname$, mymessage$, client) ' simple input handler
  55.     k$ = INKEY$
  56.     IF LEN(k$) THEN
  57.         IF k$ = CHR$(8) AND LEN(mymessage$) <> 0 THEN
  58.             mymessage$ = LEFT$(mymessage$, LEN(mymessage$) - 1)
  59.         ELSE
  60.             IF LEN(k$) = 1 AND ASC(k$) >= 32 THEN mymessage$ = mymessage$ + k$
  61.         END IF
  62.     END IF
  63.     VIEW PRINT 1 TO 24
  64.     LOCATE 22, 1: PRINT SPACE$(80); ' erase previous message displayed
  65.     LOCATE 22, 1: PRINT myname$ + ": "; mymessage$;
  66.     IF k$ = CHR$(13) THEN ' [Enter] sends the message
  67.         IF mymessage$ = "" THEN SYSTEM ' [Enter] with no message ends program
  68.         mymessage$ = myname$ + ":" + mymessage$
  69.         l = LEN(mymessage$)
  70.         PUT #client, , l
  71.         PUT #client, , mymessage$
  72.         mymessage$ = ""
  73.     END IF
  74.     IF k$ = CHR$(27) THEN SYSTEM ' [Esc] key ends program

THE CLIENT:
Code: QB64: [Select]
  1.  
  2.  
  3. PRINT "[Steve's Mini Messenger]"
  4. client = _OPENCLIENT("TCP/IP:7319:localhost") ' Attempt to connect to local host as a client
  5. PRINT "[connected to " + _CONNECTIONADDRESS(client) + "]"
  6.  
  7. INPUT "Enter your name: ", myname$
  8. out$ = myname$ + " connected!"
  9. l = LEN(out$)
  10. PUT #client, , l
  11. PUT #client, , out$
  12.     GetMessage client
  13.     SendMessage myname$, mymessage$, client ' display current input on screen
  14.     _LIMIT 30
  15.  
  16. '.................... END OF MAIN PROGRAM ................
  17.  
  18.  
  19. SUB GetMessage (client) ' get & display any new message
  20.     GET #client, , l
  21.     IF l > 0 THEN
  22.         out$ = SPACE$(l)
  23.         GET #client, , out$
  24.         VIEW PRINT 1 TO 20
  25.         LOCATE 20, 1
  26.         PRINT out$
  27.         VIEW PRINT 1 TO 24
  28.     ELSE
  29.         out$ = ""
  30.     END IF
  31.  
  32. SUB SendMessage (myname$, mymessage$, client) ' simple input handler
  33.     k$ = INKEY$
  34.     IF LEN(k$) THEN
  35.         IF k$ = CHR$(8) AND LEN(mymessage$) <> 0 THEN
  36.             mymessage$ = LEFT$(mymessage$, LEN(mymessage$) - 1)
  37.         ELSE
  38.             IF LEN(k$) = 1 AND ASC(k$) >= 32 THEN mymessage$ = mymessage$ + k$
  39.         END IF
  40.     END IF
  41.     VIEW PRINT 1 TO 24
  42.     LOCATE 22, 1: PRINT SPACE$(80); ' erase previous message displayed
  43.     LOCATE 22, 1: PRINT myname$ + ": "; mymessage$;
  44.     IF k$ = CHR$(13) THEN ' [Enter] sends the message
  45.         IF mymessage$ = "" THEN SYSTEM ' [Enter] with no message ends program
  46.         mymessage$ = myname$ + ":" + mymessage$
  47.         l = LEN(mymessage$)
  48.         PUT #client, , l
  49.         PUT #client, , mymessage$
  50.         mymessage$ = ""
  51.     END IF
  52.     IF k$ = CHR$(27) THEN SYSTEM ' [Esc] key ends program
  53.  

Have fun playing around with this as a local system messenger program.  Try it out, kick it around, and let me know if there's anything you don't understand about what it's doing.  This isn’t exactly how I'd normally write one of these; but that's because I started with what the wiki had and then gutted it and rebuilt it up until it was actually working  for me as it should.  Honestly, I think I would've been better off to have just wrote the whole program from scratch!  :P
Title: Re: Mini Messenger
Post by: Zeppelin on November 18, 2019, 05:55:15 pm
SMcNeill,
First off just wanna say thanks for actually getting TCP/IP to work. I've tried many times with the examples on the wiki.

Code: QB64: [Select]
  1. DIM SHARED Users(1 TO 1000) ' array to hold other client info
  2. DIM SHARED NumClients
  3.  
  4.  
  5. PRINT "[Steve's Mini Messenger]"
  6. host = _OPENHOST("TCP/IP:7319") ' no host found, so begin new host
  7. IF host THEN
  8.     PRINT "[Beginning new host chat session!]"
  9.     NumClients = 0
  10.     client = _OPENCLIENT("TCP/IP:7319:localhost")
  11.     IF client = 0 THEN PRINT "ERROR: could not attach host's personal client to host!"
  12.     INPUT "Enter your name:", myname$
  13.     'PRINT #client, myname$ + " connected!"
  14.     PRINT "[Chat session active!]"
  15.     PRINT "ERROR: Could not begin new host!"
  16.     PRINT "JOINING as CLIENT"
  17.  
  18.     'Join as client
  19.     client = _OPENCLIENT("TCP/IP:7319:localhost") ' Attempt to connect to local host as a client
  20. END IF ' host
  21.  
  22. IF host THEN
  23.     _TITLE "HOST"
  24.     DO ' host main loop
  25.         newclient = _OPENCONNECTION(host) ' receive any new connection
  26.         IF newclient THEN
  27.             NumClients = NumClients + 1
  28.             Users(NumClients) = newclient
  29.             PRINT "Welcome to Steve's Mini Messenger!"
  30.         END IF
  31.         FOR i = 1 TO NumClients
  32.             GetMessage Users(i) 'check all clients for a message
  33.             IF OUT$ <> "" THEN
  34.                 l = LEN(OUT$)
  35.                 FOR j = 1 TO NumClients ' distribute incoming messages to all clients
  36.                     PUT #Users(j), , l
  37.                     PUT #Users(j), , OUT$
  38.                 NEXT
  39.             END IF
  40.         NEXT i
  41.  
  42.         SendMessage myname$, mymessage$, client
  43.         _LIMIT 30
  44.     LOOP
  45.  
  46. IF client THEN
  47.     INPUT "Enter your name: ", myname$
  48.     OUT$ = myname$ + " connected!"
  49.     l = LEN(OUT$)
  50.     PUT #client, , l
  51.     PUT #client, , OUT$
  52.  
  53.     _TITLE "CLIENT"
  54.     DO
  55.         GetMessage client
  56.         SendMessage myname$, mymessage$, client ' display current input on screen
  57.         _LIMIT 30
  58.     LOOP
  59.  
  60.  
  61. SUB GetMessage (client) ' get & display any new message
  62.     GET #client, , l
  63.     IF l > 0 THEN
  64.         OUT$ = SPACE$(l)
  65.         GET #client, , OUT$
  66.         VIEW PRINT 1 TO 20
  67.         LOCATE 20, 1
  68.         PRINT OUT$
  69.         VIEW PRINT 1 TO 24
  70.     ELSE
  71.         OUT$ = ""
  72.     END IF
  73.  
  74. SUB SendMessage (myname$, mymessage$, client) ' simple input handler
  75.     k$ = INKEY$
  76.     IF LEN(k$) THEN
  77.         IF k$ = CHR$(8) AND LEN(mymessage$) <> 0 THEN
  78.             mymessage$ = LEFT$(mymessage$, LEN(mymessage$) - 1)
  79.         ELSE
  80.             IF LEN(k$) = 1 AND ASC(k$) >= 32 THEN mymessage$ = mymessage$ + k$
  81.         END IF
  82.     END IF
  83.     VIEW PRINT 1 TO 24
  84.     LOCATE 22, 1: PRINT SPACE$(80); ' erase previous message displayed
  85.     LOCATE 22, 1: PRINT myname$ + ": "; mymessage$;
  86.     IF k$ = CHR$(13) THEN ' [Enter] sends the message
  87.         IF mymessage$ = "" THEN SYSTEM ' [Enter] with no message ends program
  88.         mymessage$ = myname$ + ":" + mymessage$
  89.         l = LEN(mymessage$)
  90.         PUT #client, , l
  91.         PUT #client, , mymessage$
  92.         mymessage$ = ""
  93.     END IF
  94.     IF k$ = CHR$(27) THEN SYSTEM ' [Esc] key ends program
  95.  

Here's a version of your program that can run both client and/or host. Checks if a host is already open, then connects as client. Its just easier than having two separate programs.

Zep
Title: Re: Mini Messenger
Post by: SMcNeill on November 18, 2019, 06:44:32 pm
Here's a version of your program that can run both client and/or host. Checks if a host is already open, then connects as client. Its just easier than having two separate programs.

Zep

I agree, in many ways, I think it is too.  The only reason I placed them separate is in case someone only wanted to include the client side code for some reason.  (Perhaps to only allow a set of users to only join a game server and not have the code to actually host one themselves, or to keep compiled EXE size as small as possible...)

Thanks for taking the time and effort to assemble the pieces together for everyone else.  As you say, it's generally just a lot more convenient when everything is packaged all together for usage.  ;)
Title: Re: Mini Messenger
Post by: Cobalt on November 19, 2019, 11:34:19 am
Or If you want an example of how to use it for Network game play you can check out my Battleship 64! game.

https://www.qb64.org/forum/index.php?topic=826

the LAN network game play is\was(at that time) fully working. The basic guts of the network code is based off the Mini Messenger example from the wiki.

If anything I would Love to know how to get it running over the NET instead of just a LAN.
Title: Re: Mini Messenger
Post by: SMcNeill on November 19, 2019, 12:19:47 pm
Or If you want an example of how to use it for Network game play you can check out my Battleship 64! game.

https://www.qb64.org/forum/index.php?topic=826

the LAN network game play is\was(at that time) fully working. The basic guts of the network code is based off the Mini Messenger example from the wiki.

If anything I would Love to know how to get it running over the NET instead of just a LAN.

Don’t you need to set up your router for port forwarding for that?  Or am I overthinking things?
Title: Re: Mini Messenger
Post by: Cobalt on November 19, 2019, 01:08:15 pm
Don’t you need to set up your router for port forwarding for that?  Or am I overthinking things?

I have no idea, wonder how browsers do it? Its not like I setup anything for them to work over the web. but like I said, just something I would love to figure that out someday.
Title: Re: Mini Messenger
Post by: SMcNeill on November 19, 2019, 01:09:17 pm
If anyone is around, kindly test the following code if you can...  I'm thinking this should work as a means for folks to use the mini-messenger and connect to my home PC right now from across the interwebs...

Code: QB64: [Select]
  1.  
  2. PRINT "[Steve's Mini Messenger]"
  3. client = _OPENCLIENT("TCP/IP:80:172.93.60.23") ' Attempt to connect to local host as a client
  4. PRINT "[connected to " + _CONNECTIONADDRESS(client) + "]"
  5.  
  6. INPUT "Enter your name: ", myname$
  7. OUT$ = myname$ + " connected!"
  8. l = LEN(OUT$)
  9. PUT #client, , l
  10. PUT #client, , OUT$
  11.     GetMessage client
  12.     SendMessage myname$, mymessage$, client ' display current input on screen
  13.     _LIMIT 30
  14.  
  15. '.................... END OF MAIN PROGRAM ................
  16.  
  17.  
  18. SUB GetMessage (client) ' get & display any new message
  19.     l = 0
  20.     GET #client, , l
  21.     IF l > 0 THEN
  22.         _DELAY .1 'some delay so the other 'puter can send the info to us across spiderman's excretions!
  23.         OUT$ = SPACE$(l)
  24.         GET #client, , OUT$
  25.         VIEW PRINT 1 TO 20
  26.         LOCATE 20, 1
  27.         IF _TRIM$(OUT$) <> "" THEN PRINT OUT$
  28.         VIEW PRINT 1 TO 24
  29.     ELSE
  30.         OUT$ = ""
  31.     END IF
  32.  
  33. SUB SendMessage (myname$, mymessage$, client) ' simple input handler
  34.     k$ = INKEY$
  35.     IF LEN(k$) THEN
  36.         IF k$ = CHR$(8) AND LEN(mymessage$) <> 0 THEN
  37.             mymessage$ = LEFT$(mymessage$, LEN(mymessage$) - 1)
  38.         ELSE
  39.             IF LEN(k$) = 1 AND ASC(k$) >= 32 THEN mymessage$ = mymessage$ + k$
  40.         END IF
  41.     END IF
  42.     VIEW PRINT 1 TO 24
  43.     LOCATE 22, 1: PRINT SPACE$(80); ' erase previous message displayed
  44.     LOCATE 22, 1: PRINT myname$ + ": "; mymessage$;
  45.     IF k$ = CHR$(13) THEN ' [Enter] sends the message
  46.         IF mymessage$ = "" THEN SYSTEM ' [Enter] with no message ends program
  47.         mymessage$ = myname$ + ":" + mymessage$
  48.         l = LEN(mymessage$)
  49.         PUT #client, , l
  50.         PUT #client, , mymessage$
  51.         mymessage$ = ""
  52.     END IF
  53.     IF k$ = CHR$(27) THEN SYSTEM ' [Esc] key ends program

Note: This offer is limited in time and I don't know how long you'll be able to test this out.  Currently I'm experimenting with Firewalls down and ports being forwarded, and all that good stuff, and I'm not going to leave my PC open to the world like this forevermore...  If you test this sample and nothing happens either:

A) The code simply doesn't work...

OR

B) It works, but my PC is either off, the chat host is down, or all my firewalls are back up and denying access..    No hard feelings for anyone who misses out on the chance to playtest this little snippet with me.  ;)
Title: Re: Mini Messenger
Post by: SMcNeill on November 19, 2019, 01:52:30 pm
Chat server is currently down...  Initial tests between me and Cobalt showed that I was getting and sending information back and forth between the programs, but the simple _DELAY system I was using to wait and send responses is too inefficient to work as it currently exists.  The code above is a nice proof-of-concept test, and shows that port forwarding does work to allow our programs to talk to each other across the interwebs, but the way it's written doesn't account for lost packets, transmission times, or any other problems which may arise from when it's sent from point A to point B...

At the very least, there should probably be a checksum of some sort tossed into things to help verify the information sent...

I'm going to redo the program and see if I can get a better demo up and going for us, and share it later today/tomorrow so folks can test it out and connect to my computer here at home.  :)
Title: Re: Mini Messenger
Post by: Petr on November 19, 2019, 02:06:10 pm
Hi. I tried it now, with Bad Filename or number error message on line 6. Probably because the server is down. In a real network, when passing data through multiple routers (namely one computer was connected via wifi, the other by cable over two routers) while I was writing battleship, I found that the client and server should watch the time from sending the packet until receive is not confirmed, or after time limit must be  the packet again send. Then the counterparty should wait and send an acknowledgment upon receipt, perhaps as a LONG type with the size of the incoming packet. Perhaps a byte structure such as a PNG header would be useful, - I heard it was well written for work in network. (PNG begin and PNG end blocks)
Title: Re: Mini Messenger
Post by: SMcNeill on November 19, 2019, 02:10:42 pm
Hi. I tried it now, with Bad Filename or number error message on line 6. Probably because the server is down. In a real network, when passing data through multiple routers (namely one computer was connected via wifi, the other by cable over two routers) while I was writing battleship, I found that the client and server should watch the time from sending the packet until receive is not confirmed, or after time limit must be  the packet again send. Then the counterparty should wait and send an acknowledgment upon receipt, perhaps as a LONG type with the size of the incoming packet. Perhaps a byte structure such as a PNG header would be useful, - I heard it was well written for work in network. (PNG begin and PNG end blocks)

Aye.  It's down for now.  It's lunch time here now, but I'm going to see about reworking it and fixing it for better communication between systems, and then I'll post another version up for testing after that....

ETA... I dunno!  Hopefully soon.  ;)
Title: Re: Mini Messenger
Post by: SierraKen on November 19, 2019, 02:27:49 pm
Is this like a DCC Chat that's directly computer to computer over the Internet, or just a local LAN chat, or an Internet chat that needs a host server? I ask because first you talk about it being used locally, then later guys are talking to each other with it. I haven't tried it, just wondering, thanks.
Title: Re: Mini Messenger
Post by: SMcNeill on November 19, 2019, 02:55:06 pm
Is this like a DCC Chat that's directly computer to computer over the Internet, or just a local LAN chat, or an Internet chat that needs a host server? I ask because first you talk about it being used locally, then later guys are talking to each other with it. I haven't tried it, just wondering, thanks.

The first code is a simple little demo which works with your local computer, to allow your programs to communicate to each other, as indicated here: TCP/IP:7319:localhost

Down at Reply #6, I changed the code and the sample there is one which will allow you to communicate and trade info with the host program which is running on my PC here: TCP/IP:80:172.93.60.23

Both were working, but the code in #6 needs a little tweaking before it's fit for mass testing and lots of folks try it out, so I pulled the plug on it for now.  I'll do a rewrite, and we'll see how things look/go after that.  ;)
Title: Re: Mini Messenger
Post by: SMcNeill on November 19, 2019, 04:05:53 pm
Internet Mini-Messenger is up and going once again.  Test it out and see what happens for you.

Code: QB64: [Select]
  1.  
  2. PRINT "[Steve's Mini Messenger]"
  3. client = _OPENCLIENT("TCP/IP:7993:172.93.60.23") ' Attempt to connect to local host as a client
  4. PRINT "[connected to " + _CONNECTIONADDRESS(client) + "]"
  5.  
  6. INPUT "Enter your name: ", myname$
  7. OUT$ = myname$ + " connected!" + CHR$(10)
  8. PUT #client, , OUT$
  9.     GetMessage client
  10.     OUT$ = ""
  11.     SendMessage myname$, mymessage$, client ' display current input on screen
  12.     _LIMIT 30
  13.  
  14. '.................... END OF MAIN PROGRAM ................
  15.  
  16.  
  17. SUB GetMessage (client) ' get & display any new message
  18.  
  19.     DO
  20.         GET #client, , a$
  21.         done = -1
  22.         IF LEN(a$) > 0 THEN
  23.             OUT$ = LTRIM$(OUT$ + a$)
  24.             done = 0
  25.             l = INSTR(a$, CHR$(10))
  26.             IF l THEN done = -1:: OUT$ = LEFT$(OUT$, l - 1)
  27.         END IF
  28.         _LIMIT 30
  29.     LOOP UNTIL done
  30.  
  31.     VIEW PRINT 1 TO 20
  32.     LOCATE 20, 1
  33.     IF _TRIM$(OUT$) <> "" THEN PRINT OUT$
  34.     VIEW PRINT 1 TO 24
  35.  
  36. SUB SendMessage (myname$, mymessage$, client) ' simple input handler
  37.     k$ = INKEY$
  38.     IF LEN(k$) THEN
  39.         IF k$ = CHR$(8) AND LEN(mymessage$) <> 0 THEN
  40.             mymessage$ = LEFT$(mymessage$, LEN(mymessage$) - 1)
  41.         ELSE
  42.             IF LEN(k$) = 1 AND ASC(k$) >= 32 THEN mymessage$ = mymessage$ + k$
  43.         END IF
  44.     END IF
  45.     VIEW PRINT 1 TO 24
  46.     LOCATE 22, 1: PRINT SPACE$(80); ' erase previous message displayed
  47.     LOCATE 22, 1: PRINT myname$ + ": "; mymessage$;
  48.     IF k$ = CHR$(13) THEN ' [Enter] sends the message
  49.         IF mymessage$ = "" THEN SYSTEM ' [Enter] with no message ends program
  50.         mymessage$ = myname$ + ":" + mymessage$ + CHR$(10)
  51.         PUT #client, , mymessage$
  52.         mymessage$ = ""
  53.     END IF
  54.     IF k$ = CHR$(27) THEN SYSTEM ' [Esc] key ends program
Title: Re: Mini Messenger
Post by: Petr on November 19, 2019, 04:54:05 pm
Steve, i see your sentences. And you mine?
Title: Re: Mini Messenger
Post by: SMcNeill on November 19, 2019, 04:55:12 pm
Steve, i see your sentences. And you mine?

You need to close and restart.  My internet rebooted...  My apologies, but you guys got disconnected.
Title: Re: Mini Messenger
Post by: SMcNeill on November 19, 2019, 06:51:39 pm
Messenger is back down.  Someone keeps connecting and disconnecting without a name, spamming Welcome messages.  Many thanks to all the fine folks who tested the code.  It was a pleasure to chat with all of you!
Title: Re: Mini Messenger
Post by: STxAxTIC on November 19, 2019, 08:32:09 pm
If anyone wants to see this concept taken to a pretty far direction, I remind everyone of Sprezzo. This codebase puts all the TCP/IP and IRC stuff under the same roof. I don't use it because of the way I connect to the internet (mobile hotspot), so the institutional knowledge of this has basically disappeared. In its hay day though, I had people using a web page to send messages to IRC, or to other webpages, or to simultaneous instances of the same program, etc, etc, etc... I tried to think of everything. Happy reading:

http://barnes.x10host.com/sprezzo/index.html (http://barnes.x10host.com/sprezzo/index.html)
Title: Re: Mini Messenger
Post by: Richard on November 19, 2019, 08:53:24 pm
I tried a number of times to connect (not able to give a name) - but had to reboot my laptop many times - as my screen mode locked me onto screen 2 and would not let me view chat as screen 0 - also my wifi/mobile hotspot kept getting interrupted and had to set up again. (This may have NOTHING to do with your messenger demo).
Title: Re: Mini Messenger
Post by: SMcNeill on November 19, 2019, 10:08:27 pm
One more upgraded version of the mini messenger which works across the internet and connects to my host.

Code: [Select]
DIM SHARED OUT$, myname$, client
DIM SHARED l AS _UNSIGNED _BYTE
DIM SHARED PingTimer AS _FLOAT, LastSeen AS _FLOAT
SCREEN _NEWIMAGE(800, 600, 32)
COLOR &HFFFFFFFF, &HFF000000

PRINT "[Steve's Mini Messenger]"
client = _OPENCLIENT("TCP/IP:7993:172.93.60.23") ' Attempt to connect to local host as a client
PRINT "[connected to " + _CONNECTIONADDRESS(client) + "]"

DO
    INPUT "Enter your name: ", myname$
    myname$ = _TRIM$(myname$)
LOOP UNTIL myname$ <> ""
OUT$ = myname$ + " connected!" + CHR$(10)
PUT #client, , OUT$
PingTimer = TIMER(0.01)
LastSeen = TIMER(0.01)
DO
    GetMessage
    IF PingTimer + 30 < TIMER(0.01) THEN
        PingTimer = TIMER(0.01)
        OUT$ = "PING" + CHR$(10)
        'uncomment the below to diagnostically print when we ping the chat server
        'VIEW PRINT 1 TO 30: LOCATE 30, 1: PRINT "PING"; TIME$
        PUT #client, , OUT$
        OUT$ = ""
    END IF

    OUT$ = ""
    GetInput mymessage$ ' display current input on screen
    VIEW PRINT
    FOR i = 32 TO 35
        LOCATE i, 1: PRINT SPACE$(_WIDTH / _FONTWIDTH); ' erase previous message displayed
    NEXT
    LOCATE 32, 1: PRINT myname$ + ": "; mymessage$;
    IF INSTR(mymessage$, CHR$(10)) THEN
        OUT$ = myname$ + ":" + mymessage$
        PUT #client, , OUT$
        VIEW PRINT 1 TO 30
        LOCATE 30, 1: PRINT LEFT$(OUT$, LEN(OUT$) - 1)
        mymessage$ = ""
    END IF
    _DISPLAY
    _LIMIT 60
    IF LastSeen + 60 < TIMER(0.01) THEN 'inactive connection for too long
        VIEW PRINT 1 TO 30
        LOCATE 30, 1: PRINT "[Session Termined.  Host Timed Out.]"
        END
    END IF
LOOP

'.................... END OF MAIN PROGRAM ................


SUB GetMessage ' get & display any new message
    DO
        GET #client, , a$
        done = -1
        IF LEN(a$) > 0 THEN
            OUT$ = LTRIM$(OUT$ + a$)
            done = 0
            l = INSTR(a$, CHR$(10))
            IF l THEN
                IF OUT$ = "PONG" + CHR$(10) THEN
                    'Uncomment the following line if you want to watch the chat server talk back automatically to PING requests.
                    'VIEW PRINT 1 TO 30: LOCATE 30, 1: PRINT LEFT$(OUT$, LEN(OUT$) - 1)
                    LastSeen = TIMER(0.01)
                    OUT$ = ""
                ELSE
                    VIEW PRINT 1 TO 30: LOCATE 30, 1: PRINT LEFT$(OUT$, LEN(OUT$) - 1)
                END IF
                done = -1
            END IF
        END IF
        _LIMIT 60
    LOOP UNTIL done
END SUB

SUB GetInput (mymessage$) ' simple input handler
    k$ = INKEY$
    IF LEN(k$) THEN
        IF k$ = CHR$(8) AND LEN(mymessage$) <> 0 THEN
            mymessage$ = LEFT$(mymessage$, LEN(mymessage$) - 1)
        ELSE
            IF LEN(k$) = 1 AND ASC(k$) >= 32 THEN mymessage$ = mymessage$ + k$
        END IF
    END IF
    IF k$ = CHR$(27) OR _EXIT THEN
        OUT$ = myname$ + ": Terminated the session." 'Be nice and let the server know when we log out.
        PUT #client, , OUT$
        SYSTEM ' [Esc] key ends program
    END IF
    IF LEN(mymessage$) >= 255 THEN
        mymessage$ = mymessage$ + CHR$(10) 'autosend after 255 characters
    ELSE
        IF k$ = CHR$(13) THEN mymessage$ = mymessage$ + CHR$(10) 'so we don't send with 2 chr$(10) characters.
    END IF
END SUB

The code here is now a lot friendly for my PC... It notifies me when someone terminates a session, and it sends PINGs and PONGs every so often to make certain that both sides are still active and that the connection still exists.

I'm going to leave the chat server up and running tonight, feel free to pop in at anytime and chat with whoever might be hanging around the place if I'm not there.  No matter what, when you connect, you should get a nice entry message welcoming you to the room.  As long as you see it, you know you connected to my PC, told me hello, and my PC replied back to you.

Enjoy guys!  I don't know how much more I'll continue to work with this little demo, but I think it already has proven beyond a doubt that QB64 can be used to communicate across the internet for us.  ;)
Title: Re: Mini Messenger
Post by: Richard on November 20, 2019, 01:21:41 am
Steve

I got this virus threat warning when running your mini program (which I called X.exe)  [ This attachment cannot be displayed inline in 'Print Page' view ]  
Title: Re: Mini Messenger
Post by: Richard on November 20, 2019, 02:43:21 am
Some suggestions :-  [ This attachment cannot be displayed inline in 'Print Page' view ]  
Title: Re: Mini Messenger
Post by: SMcNeill on November 20, 2019, 07:37:35 am
Updated the code in the above post, due to user feedback.  The PONG message is now hidden by default (as it should have been, but wasn't).  Several people last night were asking, "What the heck is PONG anyway?"; here's your answer:

PING and PONG are IRC chat commands in which the host and client applications basically send a very minor amount of information back and forth to make certain that each other is still active and connected.  If the client fails to send a PING in time, the host will close their connection, free the handles, and release some memory.  If the host fails to send the PONG to the client in time, the client realizes the server has crashed, and terminates the session for the user.

It's basically just the two letting each other know they're still active and playing nicely together.  Both are 100% automated responses and not anything that the end user actually needs to worry about.  I simply had them visible for diagnostic purposes while coding the programs.   They're hidden by default now, so unless you just want to watch them spam back and forth, they should no longer be of any bother to you.  ;)

Many thanks for all the suggestions to improve the project guys; I really appreciate the interest in it.   There's just one thing here that I want to point out: I'm not out to recreate Discord, IRC, or a new chat program which will work across the internet.  I simply wanted to work up a nice demo to show that QB64 can work over TCP/IP and connect two computers across the world, and not just across a local network.  I think this demo does that for us, so I doubt I'll actually do much more work on it.

Many thanks to everyone who has tested the program out overnight (there's been 14 people so far!).  I doubt this is a program which I'll keep running 24/7 on my PC, but I will try and keep the host up and available for the next few days so everyone can test it out.  After that, it'll probably only be up "by request only", so if you want to test out the demo later, just post me a message, or send me an email, and I'll happily work with you to make it temporarily available once again.

Enjoy, one and all!  ;)
Title: Re: Mini Messenger
Post by: Petr on November 20, 2019, 11:49:29 am
Steve, add a list of connected IP addresses to the side of your computer. You can then easily deny access for spammers. Another thing - what to try files transfer?
Title: Re: Mini Messenger
Post by: SMcNeill on November 21, 2019, 09:51:32 am
The little mini-messenger chat server has been up and running for the last couple of days, and only keybone and myself have been visiting it.  It appears that the majority of everyone who is interested in this sort of thing has already tried it out by now, so I'm going to shut it down, close connections, and free up resources on my computer. 

If anyone is interested in connecting to the Mini Messenger in the future, just drop me a message and I'll pop it back online so you can play around with it and use it for testing anytime someone wants.  I just don't see any point in keeping it running 24/7 when it's just sitting there and doing nothing...  ;)
Title: Re: Mini Messenger
Post by: Cobalt on November 21, 2019, 12:05:51 pm
  I just don't see any point in keeping it running 24/7 when it's just sitting there and doing nothing...  ;)

Imagine if everyone with web servers thought that way! The web would be a much smaller place. :(

Not that I fault your logic, tis a waste of electricity(unless your running Solar or Wind that gets pricey!), and wear and tear on equipment.

I thought it was a great example and totally awesome to see it in action.