Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
TCP/IP. data from one program to another
#1
hi this is my first post. really if you want you can call me Abe, short for my real name.
there is very little documentation about this and I have been experimenting on my own but have been having problems.
i recently got interested in qb64 because it looks good more than anything else, i never used the original qb. since qb64 does not support multithreading i was looking at the wiki and i think tcp/ip might be the option. it would not be multithreading but multiprocessing but something 
is something. so i have this.

Server.bas
Code: (Select All)

_TITLE "Server"
''$SCREENHIDE
REM'$CONSOLE:ONLY
'$DYNAMIC
_DEFINE A-Z AS LONG
OPTION _EXPLICITARRAY

SCREEN 0

DIM SENDEDLONGSG(1 TO 1)
DIM SENDEDFLOATG#(1 TO 1)

DIM SHARED WWW AS STRING * 3

HOST = _OPENHOST("TCP/IP:5000")
DO
    CLIENT = _OPENCONNECTION(HOST)
    IF CLIENT <> 0 THEN
        GET #CLIENT, 1, WWW$
        PRINT "SIMPLE REQUEST"
        WWW$ = UCASE$(WWW$)
        SELECT CASE WWW$
            CASE "GSL": D = UBOUND(SENDEDLONGSG): _
                    GET #CLIENT, , SENDEDLONGSG(D): PRINT SENDEDLONGSG(D):  _
                    REDIM _PRESERVE SENDEDLONGSG(D + 1) 'GAME SEND LONG"
            CASE "GRL":_
                    D = LBOUND(SENDEDLONGSG): _
                    PUT #CLIENT, , SENDEDLONGSG(D): PRINT SENDEDLONGSG(D): _
                    Z = UBOUND(SENDEDLONGSG): _
                    if Z <> D then: FOR x = 0 TO Z STEP 1: SWAP SENDEDLONGSG(D), SENDEDLONGSG(x): NEXT: _
                    REDIM _PRESERVE SENDEDLONGSG(Z - 1):  'GAME RECEIVE LONG
            CASE "GSD": D = UBOUND(SENDEDFLOATG#): _
                    GET #CLIENT, , SENDEDFLOATG#(D): _
                    REDIM _PRESERVE SENDEDFLOATG#(D + 1) 'GAME SEND DOUBLE"
            CASE "GRF":_
                    D = LBOUND(SENDEDFLOATG#): _
                    PUT #CLIENT, , SENDEDFLOATG#(D): _
                    Z = UBOUND(SENDEDFLOATG#): _
                    IF Z<>D THEN : FOR x = 0 TO Z STEP 1: SWAP SENDEDFLOATG#(D), SENDEDFLOATG#(x): NEXT: _
                    REDIM _PRESERVE SENDEDFLOATG#(Z - 1)  'GAME RECEIVE DOUBLE
            CASE ELSE: PRINT "IDK"
        END SELECT
    END IF

    CLOSE CLIENT
    _LIMIT 20
LOOP UNTIL UCASE$(INKEY$) = "Q"

SYSTEM 0


Client.bas
Code: (Select All)

_TITLE "Client"
_DEFINE A-Z AS LONG

X = _OPENCLIENT("TCP/IP:5000:localhost")
IF X <> 0 THEN
    D$ = "GSL"
    PUT #X, , D$
    TOSEND = 80
    PRINT TOSEND
    PUT #X, , TOSEND
    _DELAY 1
    CLOSE X
ELSE
    PRINT "error no server"
    _DELAY 1
    SYSTEM 1
END IF

X = _OPENCLIENT("TCP/IP:5000:localhost")
IF X <> 0 THEN
    D$ = "GRL"
    TOSEND = -1
    PUT #X, , D$
    GET #X, , TOSEND
    PRINT TOSEND
    _DELAY 1
    CLOSE X
END IF


apparently the part where I send the data works, but when I receive them in the client, something is wrong.
   

I don't even know if the part where I manipulate the array is well done. I would like to know if you could help me to know what is wrong, I would accept any feedback, thanks.

I don't know if I'm supposed to post this like this
Reply
#2
@TheLastMan, Abe, what we are all women now?

Ha! Welcome to the forum!

I am, as yet, not interested in TCP/IP but it has been discussed many times here at the forum.
Try a search if you tire waiting for someone to answer.

Your post seems in just the right place to me. Smile

Update: here is quick link to most recent TCP/IP discussion:
https://qb64phoenix.com/forum/showthread...6#pid28986
b = b + ...
Reply
#3
Welcome, TheLastMan. Here's another good place to look. Steve's example of program to program hosting.

https://qb64phoenix.com/forum/showthread...%22host%22
Reply
#4
The underlying problem is that `GET` does not wait for the data to arrive, if the client has not yet received enough data for your variable then it simply leaves the variable as-is and sets the EOF flag. Because of that, your `PUT` followed by an immediate `GET` of a LONG is very likely to fail because the other program won't have sent its response in time. You can check for this failure by checking `EOF(X)` after the `GET`, if it's set then that indicates the `GET` was unsuccessful.

The simple solution is to just loop until `EOF()` is false, indicating you received the data. You should additionally check `_CONNECTED(X)` in the loop to determine whether the client was disconnected (you don't want to keep looping on `GET` if no data will ever come).

On the `Server.bas` side of things it gets a bit trickier. The `GET`s` in there are unlikely to fail because the messages are currently very short, but you should still be checking `EOF()` and looping to ensure they're successfully received. That approach will be ok at a certain scale but it's not ideal because during the loop the server can't do anything else and you never really know if the client will send the rest of the message. There's a large variety of solutions to this issue, but I'd consider prefixing the messages with a length, that way you can have the main code wait until an entire message is received before you start processing it, then the rest of the code can simply handle the message without having to deal with the connection.
Reply
#5
thanks, in other forums they are absurdly delicate with how you address yourself and how you write the post otherwise they almost banned you. i have bad experiences with that, people on the internet become wild very easily.
Reply
#6
https://qb64phoenix.com/forum/showthread.php?tid=2858 < Try this out and see if it helps.
Reply
#7
I got the same need some time ago and have created this as  a basis:

tcp_server.bas:
Code: (Select All)
$Console:Only
Dim Shared crlf As String * 2: crlf = Chr$(13) + Chr$(10)
Dim Shared hostConn&, conn&(100), conns%

hostConn& = _OpenHost("TCP/IP:1234")
Print _ConnectionAddress$(hostConn&)

Do
  _Limit 10
  newConn& = _OpenConnection(hostConn&)
  If newConn& <> 0 Then
    conns% = conns% + 1: conn&(conns%) = newConn&
    Print "connections:"; conns%
  End If

  If Abs(Timer - tim!) > .1 Then
    out$ = Time$ + " "
    c% = 1
    Do While c% <= conns%
      If _Connected(conn&(c%)) = 0 Then
        Close conn&(c%)
        For i% = c% + 1 To conns%
          conn&(i% - 1) = conn&(i%)
        Next i%
        conns% = conns% - 1
        Print "connections:"; conns%
      Else
        Get #conn&(c%), , in$: If in$ <> "" Then Print c%, in$
        Put #conn&(c%), , out$
      End If
      c% = c% + 1
    Loop
    tim! = Timer
  End If
Loop Until InKey$ <> ""

Close hostConn&
System

tcp_clients.bas:
Code: (Select All)
Do
  _Limit 20

  Do
    m$ = receive$
    If m$ <> "" Then Print m$;
  Loop Until m$ = ""
Loop Until InKey$ = Chr$(27)
Close connect&
System

Function send& (m$)
  c& = connect&
  If c& Then Put #c&, , m$
  send& = c&
End Function

Function receive$
  c& = connect&
  If c& Then Get #c&, , m$
  receive$ = m$
End Function

Function connect&
  Static conn&, hconn&
  If conn& Then If _Connected(conn&) Then connect& = conn&: Exit Function
  If hconn& Then
    conn& = _OpenConnection(hconn&)
  Else
    conn& = _OpenClient("TCP/IP:1234:localhost")
    If Not conn& Then
      hconn& = _OpenHost("TCP/IP:1234")
      If hconn& Then conn& = _OpenConnection(hconn&)
    End If
  End If
  connect& = conn&
End Function

All client messages are sent to all other clients
45y and 2M lines of MBASIC>BASICA>QBASIC>QBX>QB64 experience
Reply




Users browsing this thread: 1 Guest(s)