Author Topic: Feature request. ICMP (ping) routine.  (Read 4366 times)

0 Members and 1 Guest are viewing this topic.

Offline Chris80194

  • Newbie
  • Posts: 42
    • View Profile
Feature request. ICMP (ping) routine.
« on: December 11, 2018, 01:25:55 am »
Not sure where to put a request.
I would like to be able to ping a ip to verify status up or down.
CMD is a dirty way to do this.
Is there  way to add ICMP to QB64 the same as how TCPIP has been added?
Would be a nice feature built in.

Marked as best answer by Chris80194 on December 14, 2018, 08:30:47 pm

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Re: Feature request. ICMP (ping) routine.
« Reply #1 on: December 12, 2018, 11:03:50 am »
when you want to 'ping' an IP do you mean like any internet site, QB64.org, Google, Yahoo. facebook, ect.. or do you mean a networked computer or user to see if they are still connected, for like a game or program? For the former I don't think I can help but for the latter this is what I usually put in my code,

 for the host side:
Code: QB64: [Select]
  1. SUB PingClients
  2.  IF NumClients > 0 THEN 'only bother if there are clients
  3.   FOR I = 1 TO NumClients ' distribute PING message to all clients
  4.    IF Users(I).Id THEN
  5.     PUT #Users(I).Id, , PING
  6.     Users(I).PingTime = UpTime&
  7.    END IF
  8.   NEXT I
  9.   LastPing = UpTime&
  10.  

and the client side:
Code: QB64: [Select]
  1. 'inside a loop-----
  2. GET #ID&, , newmessage$
  3. IF LEFT$(newmessage$, 4) = "PING" THEN SendPing ID&
  4. '---------------------
  5.  
  6. SUB SendPing (id&)
  7.  PUT #id&, , PING
  8.  Response%% = TRUE
  9.  

and once the host sends the ping the client has a certain amount of time to reply or is considered 'disconnected' or lost. and gets removed from the client array.

I think if you can use one of the QB64 commands to have a similar result with online sites, but not sure as I have never played with it. Luke used to have a bot in the IRC chat room that would pull from Wikipedia the same process could probably be used to check whether a site was up or not based on a time out. but not sure there of course.
Granted after becoming radioactive I only have a half-life!

Offline Chris80194

  • Newbie
  • Posts: 42
    • View Profile
Re: Feature request. ICMP (ping) routine.
« Reply #2 on: December 14, 2018, 10:11:08 pm »
I have a headache from a routeing issue that should have been a simple fix but has become an reengineering nightmare.

So I will try out your code snippets to see if that is what I wanted to accomplish.

Basically in my feeble mind the idea was to Ping 192.168.1.1 and get a reply back then set a flag of up or down.  I wanted to do this with out a Shell/CMD in and out of the program and creating a temp file to read, it would probably be nice to also ping yahoo.com and get a reply back too from a url instead of just an ip.

The code looks interesting and I will give that a try to see.

I was thinking of maybe setting a _ICMP command like the _CONNECT command in qb64.......

Thanks for the response, im going to now try out you code snips.
« Last Edit: December 14, 2018, 10:29:18 pm by Chris80194 »

Offline Chris80194

  • Newbie
  • Posts: 42
    • View Profile
Re: Feature request. ICMP (ping) routine.
« Reply #3 on: December 14, 2018, 10:21:55 pm »
This might kinda work it needs a host and client which I was kinda banging something on my own that never worked.  As a intermediate process This might do what I want i need to run this one each system though not what I had envisioned but could work for a small network.

Like I mentioned I was thinking of a built in _ICMP command and that would work together with TCPIP transfers to verify if a ip or hostname was alive before running a _CONNECT attempt.
Ping or ICMP does not have a port number since it works on another network layer.

QB64 is c++ right?  So could I do a include of a library that is written in c++ ???
« Last Edit: December 14, 2018, 10:30:00 pm by Chris80194 »

Offline Chris80194

  • Newbie
  • Posts: 42
    • View Profile
Re: Feature request. ICMP (ping) routine.
« Reply #4 on: December 14, 2018, 10:56:34 pm »
I guess I am missing something it looks like the code is not complete????

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Re: Feature request. ICMP (ping) routine.
« Reply #5 on: December 16, 2018, 07:58:43 pm »
I guess I am missing something it looks like the code is not complete????

no that is not the complete code that is just the vitals, you must define PING of course
the client has it defined as:
PING = "PONG"

and the host has it defined as
PING = "PING"

in both programs PING is DIM SHARED PING as STRING*4

there is a good bit involved in running the host and client, I was just showing the parts the were responsible for checking if a client was still connected.
here is the code so far, still haven't added all the functions I wanted but it connected and did basic operating.
HOST:
Code: QB64: [Select]
  1. TYPE clients
  2.  PingTime AS LONG
  3.  Id AS LONG
  4. DIM SHARED HostID&, UpTime&, NumClients AS INTEGER, PING AS STRING * 4
  5. DIM SHARED LastPing AS LONG, LastJoin AS LONG, NICK(1 TO 1000) AS STRING
  6. DIM SHARED Users(1 TO 1000) AS clients ' array to hold other client info
  7. CONST TRUE = -1, FALSE = NOT TRUE
  8. PING = "PING"
  9.  
  10. Update& = _FREETIMER
  11. ON TIMER(Update&, .5) DisplayStats 'timer for Host status.
  12. Pong& = _FREETIMER
  13. ON TIMER(Pong&, 60) PingClients
  14.  
  15. 'OPEN "HostDebug.txt" FOR OUTPUT AS #3
  16.  
  17. SCREEN _NEWIMAGE(80, 10, 0) 'Reduced screen Size for Host info.
  18. _TITLE "Host: Setting up...."
  19. IF StartHost(0) THEN
  20.  TIMER(Update&) ON
  21.  TIMER(Pong&) ON
  22.  HostMain HostID&
  23.  TIMER(Update&) OFF
  24.  TIMER(Pong&) OFF
  25.  PRINT "Error starting up host"
  26.  
  27.  
  28.  
  29.  
  30.  
  31.  
  32.  
  33. SUB HostMain (ID&)
  34.  _TITLE "Host - Connection:" + _CONNECTIONADDRESS(HostID&)
  35.  NumClients = 0
  36.  DO ' host main loop
  37.   newclient = _OPENCONNECTION(ID&) ' receive any new connection
  38.   IF newclient THEN
  39.    NumClients = NumClients + 1
  40.    Users(NumClients).Id = newclient
  41.    LastJoin = UpTime&
  42.   END IF
  43.   FOR I = 1 TO NumClients ' distribute incoming messages to all clients
  44.    IF Users(I).Id THEN
  45.     GET #Users(I).Id, , message$
  46.     IF message$ = "PONG" THEN Users(I).PingTime = -1 'User Replied to PING
  47.     IF message$ = "LEAVING" THEN DropUser I 'user quits
  48.     IF LEFT$(message$, 5) = "HELLO" THEN AddNick message$, I 'get new user nickname
  49.     IF Users(I).PingTime > 0 AND Users(I).PingTime + 45 = UpTime& THEN DropUser I 'Client Failed to pong
  50.     IF LEFT$(message$, 4) = "TALK" THEN PRINT "Message recieved": MessageParse I, message$
  51.    END IF
  52.   NEXT I
  53.   _DELAY 0.04 ' reduce CPU usage
  54.   IF INKEY$ = CHR$(27) THEN ExitFlag%% = TRUE
  55.  LOOP UNTIL ExitFlag%%
  56.  PRINT "Shutting down Host"
  57.  
  58. 'open host for file transfer
  59. FUNCTION StartHost (port%)
  60.  IF port% = 0 THEN default% = 1979 ELSE default% = port%
  61.  ID$ = "TCP/IP:" + LTRIM$(STR$(default%))
  62.  HostID& = _OPENHOST(ID$) 'begin new host
  63.  Result = HostID&
  64.  StartHost = Result
  65.  
  66. 'Current Status
  67. SUB DisplayStats
  68.  STATIC click%%
  69.  LOCATE 1, 1: PRINT "Host Up Time-"; Clock$(UpTime&); "("; UpTime&; ")"
  70.  LOCATE 2, 1: PRINT "Client Count-"; NumClients
  71.  LOCATE 3, 1: PRINT "Last Ping At-"; Clock$(LastPing)
  72.  LOCATE 4, 1: PRINT "Last Join At-"; Clock$(LastJoin)
  73.  IF NumClients > 0 THEN LOCATE 5, 1: PRINT "Who Joined  -"; NICK(NumClients) ELSE LOCATE 5, 1: PRINT SPACE$(79)
  74.  click%% = click%% + 1
  75.  IF click%% = 2 THEN UpTime& = UpTime& + 1: click%% = 0
  76.  
  77. FUNCTION Clock$ (tim&)
  78.  Secs%% = tim& MOD 60
  79.  Mins%% = (tim& - Secs%%) / 60
  80.  Hrs%% = INT(Mins%% / 60) - .49
  81.  Mins%% = Mins%% MOD 60
  82.  IF Hrs%% < 10 THEN H$ = "0" + LTRIM$(STR$(Hrs%%)) ELSE H$ = LTRIM$(STR$(Hrs%%))
  83.  IF Mins%% < 10 THEN M$ = "0" + LTRIM$(STR$(Mins%%)) ELSE M$ = LTRIM$(STR$(Mins%%))
  84.  IF Secs%% < 10 THEN S$ = "0" + LTRIM$(STR$(Secs%%)) ELSE S$ = LTRIM$(STR$(Secs%%))
  85.  Clock$ = H$ + ":" + M$ + ":" + S$
  86.  
  87. SUB PingClients
  88.  IF NumClients > 0 THEN 'only bother if there are clients
  89.   FOR I = 1 TO NumClients ' distribute PING message to all clients
  90.    IF Users(I).Id THEN
  91.     PUT #Users(I).Id, , PING
  92.     Users(I).PingTime = UpTime&
  93.    END IF
  94.   NEXT I
  95.   LastPing = UpTime&
  96.   SendUpTime UpTime&
  97.  
  98. SUB DropUser (id%)
  99.  'if user sends "LEAVING" message or fails to respond to a PING
  100.  'then drop the user
  101.  FOR J% = id% TO NumClients
  102.   SWAP Users(J%), Users(J% + 1)
  103.   SWAP NICK(J%), NICK(J% + 1)
  104.  NEXT J%
  105.  Users(J%).Id = 0
  106.  Users(J%).PingTime = 0
  107.  NICK(J%) = ""
  108.  NumClients = NumClients - 1
  109.  
  110. SUB MessageParse (WhoFrom&, Txt$)
  111.  'find who the message is for
  112.  Txt$ = MID$(Txt$, 5)
  113.  match% = FALSE
  114.  FOR i% = 1 TO NumClients
  115.   IF LCASE$(MID$(Txt$, 1, INSTR(Txt$, ":") - 1)) = LCASE$(NICK(i%)) THEN match% = i%: i% = NumClients + 1
  116.  NEXT i%
  117.  '---------------------------
  118.  'pull message body
  119.  MSG$ = MID$(Txt$, INSTR(Txt$, ":") + 1)
  120.  '---------------------------
  121.  MSG$ = NICK(WhoFrom&) + " SAYS: " + CHR$(34) + MSG$ + CHR$(34)
  122.  'send message to right client(hopefully)
  123.  IF match% THEN
  124.   PUT #Users(match%).Id, , MSG$
  125.  ELSE 'no name given send to all clients
  126.   FOR i% = 1 TO NumClients
  127.    PUT #Users(i%).Id, , MSG$
  128.   NEXT i%
  129.  '---------------------------
  130.  
  131.  
  132. SUB DataParse (WhoFrom&, Dat$)
  133.  
  134.  
  135. SUB AddNick (TXT$, WHO&)
  136.  InUse%% = FALSE
  137.  temp$ = MID$(TXT$, 7) 'get new user Nickname
  138.  'make sure name is not already in use
  139.  FOR i% = 1 TO NumClients
  140.   IF LCASE$(RTRIM$(temp$)) = LCASE$(NICK(i%)) THEN InUse%% = TRUE: i% = NumClients + 1
  141.  NEXT i%
  142.  IF InUse%% THEN
  143.   MSG$ = "BADNICK"
  144.   PUT #Users(WHO&).Id, , MSG$
  145.   NICK(WHO&) = RTRIM$(temp$)
  146.  
  147.  
  148. SUB SendUpTime (t&)
  149.  FOR i% = 1 TO NumClients
  150.   TXT$ = "DATASTRGTIME" + Clock$(UpTime&)
  151.   PUT #Users(i%).Id, , TXT$
  152.  NEXT i%
  153.  

CLIENT:
Code: QB64: [Select]
  1. DIM SHARED Message AS STRING, MyName$, UpTime&, Response%%
  2. DIM SHARED ClientID&, PING AS STRING * 4, QUIT AS STRING * 7
  3. DIM SHARED HostTime$
  4. CONST TRUE = -1, FALSE = NOT TRUE
  5. QUIT = "LEAVING": PING = "PONG"
  6.  
  7. Update& = _FREETIMER
  8. ON TIMER(Update&, .5) StatusUpdate 'timer for Host status.
  9.  
  10. LOCATE , , 1 ' display the print cursor for INKEY$
  11. _TITLE "Client - Connecting..."
  12. INPUT "Enter your name: ", MyName$
  13. INPUT "Enter Host IP address(0-Local)"; IPA$
  14. INPUT "Enter Hosts Port(0-default)"; port%
  15.  
  16. IF ConnectClient(port%, IPA$) THEN
  17.  CLS: TIMER(Update&) ON
  18.  SendNick MyName$, ClientID&
  19.  ClientMain ClientID&
  20.  PRINT "Error Connecting to Host"
  21.  
  22.  
  23.  
  24. FUNCTION ConnectClient (port%, IPA$)
  25.  IF port% = 0 THEN default% = 1979 ELSE default% = port%
  26.  IF IPA$ = "0" THEN IP$ = ":localhost" ELSE IP$ = ":" + IPA$
  27.  ID$ = "TCP/IP:" + LTRIM$(STR$(default%)) + IP$
  28.  ClientID& = _OPENCLIENT(ID$) ' Attempt to connect to local host as a client
  29.  Result = ClientID&
  30.  ConnectClient = Result
  31.  
  32. SUB ClientMain (ID&)
  33.  _TITLE "Client - Connected - " + MyName$
  34.  DO
  35.   GetMessage ID&
  36.   '  SendMessage MyName$, MyMessage$, ID& ' display current input on screen
  37.   _DELAY 0.0416 ' reduce CPU usage
  38.  
  39.   KBD$ = INKEY$
  40.   SELECT CASE KBD$
  41.    CASE CHR$(27)
  42.     ExitFlag%% = TRUE
  43.    CASE CHR$(13)
  44.     SendMessage
  45.    CASE ELSE
  46.     TypeMessage KBD$
  47.  
  48.  LOOP UNTIL ExitFlag%%
  49.  PUT #ClientID&, , QUIT
  50.  PRINT "Disconnected from host"
  51.  
  52. SUB SendPing (id&)
  53.  PUT #id&, , PING
  54.  Response%% = TRUE
  55.  
  56. SUB GetMessage (ID&) ' get & display any new message
  57.  STATIC pingcount~%
  58.  GET #ID&, , newmessage$
  59.  IF LEFT$(newmessage$, 4) = "PING" THEN SendPing ID&: Response%% = FALSE: LOCATE 5, 1: PRINT "You Got Pinged! Time Was:"; TIME$: pingcount~% = pingcount~% + 1: PRINT pingcount~%: newmessage$ = MID$(newmessage$, 5)
  60.  'if the nick is in use ask user for new, if it takes too long to reply
  61.  'the host will kick client.
  62.  IF newmessage$ = "BADNICK" THEN LOCATE 1, 1: INPUT "Name Already In Use, Pick New Name"; MyName$: SendNick MyName$, ID&
  63.  IF LEFT$(newmessage$, 4) = "DATA" THEN ProcessPacket newmessage$
  64.  IF INSTR(newmessage$, "SAYS:") THEN ShowMessages MID$(newmessage$, INSTR(newmessage$, ":") + 1)
  65.  
  66. SUB SendNick (tag$, id&)
  67.  MSG$ = "HELLO:" + tag$
  68.  PUT #id&, , MSG$
  69.  
  70. SUB TypeMessage (txt$)
  71.  SELECT CASE txt$
  72.   CASE CHR$(8) 'back space
  73.    Message = LEFT$(Message, LEN(Message) - 1)
  74.   CASE CHR$(32) TO CHR$(126)
  75.    Message = Message + txt$
  76.  DisplayMessage
  77.  
  78. SUB DisplayMessage
  79.  LOCATE 23, 1
  80.  IF LEN(Message) < 70 THEN
  81.   PRINT Message; SPACE$(70 - LEN(Message))
  82.  ELSE 'message longer than line
  83.   PRINT MID$(Message, LEN(Message) - 70)
  84.  
  85. SUB SendMessage () ' (ToWho$)
  86.  IF INSTR(Message, ":") THEN 'if message is to certain client
  87.   MSG$ = "TALK" + Message
  88.  ELSE 'other wise send to all
  89.   MSG$ = "TALK  :" + Message
  90.  PUT #ClientID&, , MSG$
  91.  Message = ""
  92.  
  93. SUB ShowMessages (txt$)
  94.  'define message area
  95.  VIEW PRINT 3 TO 21
  96.  'display message
  97.  LOCATE 21, 1: PRINT txt$
  98.  'restore screen area
  99.  VIEW PRINT 1 TO 24
  100.  
  101. SUB ProcessPacket (txt$)
  102.  txt$ = MID$(txt$, 5) 'remove DATA from string
  103.  'what type of value
  104.  SELECT CASE LEFT$(txt$, 4)
  105.   CASE "BYTE"
  106.    d%% = VAL(MID$(txt$, 5))
  107.   CASE "INTR"
  108.    d% = VAL(MID$(txt$, 5))
  109.   CASE "LONG"
  110.    d& = VAL(MID$(txt$, 5))
  111.   CASE "SNGL"
  112.    d! = VAL(MID$(txt$, 5))
  113.   CASE "DUBL"
  114.    d& = VAL(MID$(txt$, 5))
  115.   CASE "STRG"
  116.    IF MID$(txt$, 5, 4) = "TIME" THEN
  117.     HostTime$ = MID$(txt$, 9)
  118.    ELSE
  119.     d$ = MID$(txt$, 5)
  120.    END IF
  121.  
  122. SUB StatusUpdate
  123.  LOCATE 1, 1: PRINT "Host Up Time:"; HostTime$
  124.  LOCATE 1, 25: PRINT "PING Response Yet?";
  125.  IF Response%% THEN PRINT "Yes" ELSE PRINT "No "
  126.  

They are dirty and messy and not complete, just doing some basic R&D for my Battleship game.
You can use a DLL, if you know what you need but that is beyond my experience I fear.
Granted after becoming radioactive I only have a half-life!

Offline Chris80194

  • Newbie
  • Posts: 42
    • View Profile
Re: Feature request. ICMP (ping) routine.
« Reply #6 on: December 19, 2018, 05:32:00 am »
I will give that a go then.
Thanks,

PS.
The ICMP idea was a out of the box thinking idea to augment the other built-in tcpip commands.
« Last Edit: December 19, 2018, 05:33:31 am by Chris80194 »