Author Topic: Help with a Simple file transfer from a client to the host to send 2 text files.  (Read 403 times)

Client file code
Code: [Select]
' Client computer: Sends the file

'INPUT "Enter a port number to broadcast on: ", port$
port$ = "12345" 'comment out demo code

'INPUT "Enter the IP number to connect to: ", ipnum$
ipnum$ = "192.168.3.208" 'comment out demo code

wconnect$ = "TCP/IP:" + port$ + ":" + ipnum$

'INPUT "Enter the name of a file to send: ", s$
's$ = "Mileage.csv" 'comment out demo code
't$ = "TripLog.csv"
S$ = "test2."
T$ = "test1."

PRINT "try to connect to Station " + wconnect$
PRINT "This Station IP is " + GetLocalIP$
PRINT "Send Files " + S$ + " " + T$
client = _OPENCLIENT(wconnect$)
IF client = 0 THEN PRINT "Could not connect!": END

PRINT "Sending " + S$ + "..."
PRINT #client, S$
OPEN S$ FOR BINARY AS #2
size& = LOF(2)
PRINT #client, size&
BufferSize& = 1024
BytesPerSecond& = 1048576
Buffer$ = SPACE$(BufferSize&)
FOR o& = 1 TO size& STEP BufferSize&
    IF o& + BufferSize& - 1 > size& THEN Buffer$ = SPACE$(size& - o& + 1)
    GET #2, , Buffer$
    PUT #client, , Buffer$
    _DELAY BufferSize& / BytesPerSecond&
    PRINT ".";
NEXT
PRINT 'new line
CLOSE #2
'CLOSE #client
PRINT "File " + S$ + " sent successfully!"

PRINT "Sending " + T$ + "..."
PRINT #client, T$
OPEN T$ FOR BINARY AS #2
size& = LOF(2)
PRINT #client, size&
BufferSize& = 1024
BytesPerSecond& = 1048576
Buffer$ = SPACE$(BufferSize&)
FOR o& = 1 TO size& STEP BufferSize&
    IF o& + BufferSize& - 1 > size& THEN Buffer$ = SPACE$(size& - o& + 1)
    GET #2, , Buffer$
    PUT #client, , Buffer$
    _DELAY BufferSize& / BytesPerSecond&
    PRINT ".";
NEXT
PRINT 'new line
CLOSE #2
CLOSE #client
PRINT "File " + T$ + " sent successfully!"

FUNCTION GetLocalIP$
    SHELL _HIDE "cmd /c ipconfig > IPconfig.tmp"
    A = FREEFILE
    OPEN "IPconfig.tmp" FOR INPUT AS #A
    DO
        LINE INPUT #A, ipline$
        IF UCASE$(LEFT$(LTRIM$(ipline$), 4)) = "IPV4" THEN
            GetLocalIP$ = MID$(ipline$, INSTR(ipline$, ":") + 2)
            IF GetLocalIP$ = "127.0.0.1" THEN GOTO 77
            CLOSE #A
            KILL "IPconfig.tmp" 'kill the messenger?
            EXIT DO
            77
        END IF
    LOOP UNTIL EOF(1)

END FUNCTION

The above code acts like it connects and sends the files named in the code just simple text files

The Host connects and spits out Zero and Zero in 2 columns and wont return to :1 to start over and wait, so it could receive another file if another one would be sent.

Code: [Select]
' Host Computer: Receives the file

'INPUT "Enter the port number to listen on: ", port$
1
COLOR 7, 4
CLS
CLOSE

port$ = "12345" 'comment out demo code

v$ = "TCP/IP:" + port$
host = _OPENHOST(v$)
TTime$ = DATE$ + "_" + LEFT$(TIME$, 2) + "." + MID$(TIME$, 4, 2) + "." + RIGHT$(TIME$, 2) + ".TXT"
Path$ = "C:\Users\Chris\Downloads\Files"
Receive$ = Path$ + TTime$
Logging$ = Path$ + "IPLOG.txt"
LOCATE 10, 27: PRINT "Esc to shut down host."
IF host <> 0 THEN LOCATE 12, 20: PRINT GetLocalIP$ + ":" + port$; " You are the host."
LOCATE 11, 20: PRINT "Path to save to is " + Path$

DO
    keyed$ = INKEY$
    IF keyed$ = CHR$(27) THEN SYSTEM
    newclient = _OPENCONNECTION(host)
    IF newclient <> 0 THEN
        PRINT "Another computer has connected! "
        B = FREEFILE
        OPEN Logging$ FOR APPEND AS #B
        IP$ = _CONNECTIONADDRESS(newclient)
        PRINT IP$ + " has joined." ' displayed to Host only
        PRINT #B, IP$, TTime$ ' print info to a log file
        CLOSE B

        DO
            INPUT #newclient, s$
        LOOP UNTIL EOF(newclient) = 0

        '        DO
        '       INPUT #newclient, size&
        '      LOOP UNTIL EOF(newclient) = 0

        PRINT "Downloading " + s$ + "... To " + Receive$
        C = FREEFILE
        PRINT "--------------------------------"
        PRINT newclient
        PRINT EOF(newclient)
        PRINT s$
        PRINT size&
        PRINT "--------------------------------"

        OPEN Receive$ + s$ FOR OUTPUT AS #C
        filesize& = 0
        DO
            GET #newclient, , UT$
            filesize& = filesize& + LEN(UT$)
            IF LEN(t$) THEN PRINT #C, , UT$: PRINT ".";
            _DELAY 0.01
            PRINT filesize&, size&
            '        LOOP UNTIL filesize& = size&
        LOOP
        PRINT 'newline
        CLOSE #B
        CLOSE #newclient
        PRINT s$ + Receive$ + s$ + " successfully!"
    END IF
LOOP

DO
    keyed$ = INKEY$
    IF keyed$ = CHR$(27) THEN SYSTEM
    newclient = _OPENCONNECTION(host)
    IF newclient <> 0 THEN
        PRINT "Another computer has connected! "
        B = FREEFILE
        OPEN Logging$ FOR APPEND AS #B
        IP$ = _CONNECTIONADDRESS(newclient)
        PRINT IP$ + " has joined." ' displayed to Host only
        PRINT #B, IP$, TTime$ ' print info to a log file
        CLOSE B

        DO
            INPUT #newclient, t$
        LOOP UNTIL EOF(newclient) = 0

        '        DO
        '       INPUT #newclient, size&
        '      LOOP UNTIL EOF(newclient) = 0

        PRINT "Downloading " + t$ + "... To " + Receive$
        C = FREEFILE
        PRINT "--------------------------------"
        PRINT newclient
        PRINT EOF(newclient)
        PRINT t$
        PRINT size&
        PRINT "--------------------------------"

        OPEN Receive$ + t$ FOR OUTPUT AS #C
        filesize& = 0
        DO
            GET #newclient, , UT$
            filesize& = filesize& + LEN(UT$)
            IF LEN(t$) THEN PRINT #C, , UT$: PRINT ".";
            _DELAY 0.01
            PRINT filesize&, size&
            '        LOOP UNTIL filesize& = size&
        LOOP
        PRINT 'newline
        CLOSE #B
        CLOSE #newclient
        PRINT t$ + Receive$ + t$ + " successfully!"
    END IF
LOOP
GOTO 1

FUNCTION GetLocalIP$
    SHELL _HIDE "cmd /c ipconfig > IPconfig.tmp"
    A = FREEFILE
    OPEN "IPconfig.tmp" FOR INPUT AS #A
    DO
        LINE INPUT #A, ipline$
        IF UCASE$(LEFT$(LTRIM$(ipline$), 4)) = "IPV4" THEN
            GetLocalIP$ = MID$(ipline$, INSTR(ipline$, ":") + 2)
            IF GetLocalIP$ = "127.0.0.1" THEN GOTO 77
            CLOSE #A
            KILL "IPconfig.tmp" 'kill the messenger?
            EXIT DO
            77
        END IF
    LOOP UNTIL EOF(1)

END FUNCTION

This looks like it should be a simple fix but TCP was not around when I leaned Basic code.
Thank you for your help.

Ps. I would like a snip of code to verify if a certain IP or maybe domain name can be reached before making an automated attempt in the client side.
Thanks again
« Last Edit: November 13, 2018, 03:19:59 AM by Chris80194 »

Offline Petr

  • I am instructed.
I think, you search IF _CONNECTED (connectionhandle&)? I have a TCP / IP transmission program somewhere, but I have to find it first

Offline FellippeHeitor

  • QB64 Developer
  • LET IT = BE
    • QB64.org
I'm still to give your code a more thorough read but one thing caught my eye at a first glance: don't use PRINT and INPUT with TCP/IP. Use GET/PUT. I'll get back to you later after I've had time to analyse it further.

Petr How would I use  IF _CONNECTED (connectionhandle&)
Just like that or do I need to add a loop of some kind?  Thanks


FellippeHeitor GET/PUT ill have to change those into the program.... I think the print and input was in the original code snippet that I found.  Thanks

Please keep in touch with any ideas and updates, Thanks.

Offline Petr

  • I am instructed.
Hi. I found the program, which use it:

Code: [Select]
'NETWORK File transfer demo program.


DIM SHARED Host AS LONG, Client AS LONG
DIM InFile AS STRING * 128, OutFile AS STRING * 128, ok AS STRING * 2
CONST PACKET = 4096



I_am = Network("localhost")
InFile$ = "Z:\op_copy.avi" '             1899 megabytes file                         Both this strings are always 128 bytes long (DIM)
OutFile$ = "E:\copy.wav" '    copy send via network to this client place


SELECT CASE I_am
    CASE 1 'HOST   -    in this demo HOST send FILE to client
        _TITLE "Host"
        IF _FILEEXISTS(InFile$) THEN OPEN InFile$ FOR BINARY AS #1 ELSE BEEP: PRINT "File for transfer (source) not found"; InFile$: END
        PRINT "Sending File name and file size...("; RTRIM$(InFile$); " and"; LOF(1); LTRIM$(")")
        res$ = InFile$ + MKL$(LOF(1)) '                       size is set by DIM for InFile$ + 4 bytes LONG value for file size
        PUT #Host, , res$ '                                   send file name and file size
        _DELAY .005
        PRINT "Waiting for confirmation of the name and size ..."

        ok$ = Transfer$(Host, 2)
        IF ok$ = "OK" THEN PRINT "Name and size transferred correctly." ELSE END
        ok$ = ""

        PRINT "Uploading file..."

        zbyva& = LOF(1) '                               This variable in begin is the same value as uploaded file size
        DO WHILE zbyva& > 0 '                           Block for transport is 10 000 000 bytes, upload until all bytes are send
            IF zbyva& > PACKET THEN Block$ = SPACE$(PACKET) ELSE Block$ = SPACE$(zbyva&)
            zbyva& = zbyva& - PACKET
            GET #1, , Block$ '
            PUT #Host, , Block$
            IF LOF(1) > PACKET THEN DO UNTIL Transfer$(Host, 2) = "OK": LOOP '   wait for confirmation, that all bytes from 10 000 000 bytes packet comming to CLIENT.
        LOOP '                                           THEN is next packet send.

        PRINT "Waiting for confirmation FILE SIZE"
        message$ = Transfer$(Host&, 4) '                 It checks if the created and written file is the same size as the source file
        IF CVL(message$) = LOF(1) THEN PRINT "Image transferred correctly. ": END ELSE PRINT "Post:"; LOF(1); "bytes, but received"; CVL(message$); "bytes!"
    CASE 2 'CLIENT - in this demo receive and write file
        _TITLE "Client"

        PRINT "Receiving info about file..."
        file$ = Transfer$(Client, 132)
        FileName$ = LTRIM$(LEFT$(file$, 128)) ' maximal file name lenght is set by DIM to 128 bytes in this program
        FileSize& = CVL(RIGHT$(file$, 4))
        PRINT "File in transfer: "; RTRIM$(FileName$)
        PRINT "File size (bytes): "; FileSize&

        PRINT "Confirm file name and file size ..."
        ok$ = "OK"
        PUT #Client, , ok$


        'if filesize is smaller than 10 000 000 bytes, use standard way without blocks
        IF FileSize& < PACKET THEN
            Content$ = Transfer$(Client, FileSize&)

            OPEN RTRIM$(OutFile$) FOR OUTPUT AS #2: CLOSE #2 '     create new clear file - in this case named differently, but in real network use File_Name$, here its for localhost test in the same directory
            OPEN RTRIM$(OutFile$) FOR BINARY AS #2 '               write binary data to file
            PRINT "Writing file..."
            PUT #2, , Content$
            Writed_Size& = LOF(2)
            CLOSE #2
            confirm$ = MKL$(Writed_Size&) '                        client post WRITED SIZE as control back to Host
            PUT #Client&, , confirm$
            IF Writed_Size& = FileSize& THEN PRINT "Transfer OK!"


        ELSE 'if file is bigger than 10 000 000  bytes, use blocks:
            OPEN RTRIM$(OutFile$) FOR OUTPUT AS #2: CLOSE #2 '     create new clear file - in this case named differently, but in real network use File_Name$, here its for localhost test in the same directory
            OPEN RTRIM$(OutFile$) FOR BINARY AS #2 '               write binary data to file
            zbyva& = FileSize&

            IF FileSize& > 0 THEN '                                For percentage transfer calculation
                IF FileSize& MOD PACKET THEN TB = 1
                TotalBlocks = INT(FileSize& / PACKET) + TB
            END IF
            Ln = CSRLIN
            'in every loop in transmitted one 10 000 000 bytes lenght block
            DO WHILE zbyva& > 0
                IF zbyva& > PACKET THEN Block$ = Transfer$(Client, PACKET) ELSE Block$ = Transfer$(Client, zbyva&)
                zbyva& = zbyva& - PACKET
                PUT #2, , Block$
                ok$ = "OK"
                PUT #Client, , ok$ '                                send confirmation, that this block is writed and can be send next by HOST

                Block = Block + 1
                Block$ = ""
                perc = INT(100 * (Block / TotalBlocks))
                IF oldperc <> perc THEN oldperc = perc: LOCATE Ln,: PRINT "Block "; Block; "/"; TotalBlocks; "("; perc; "%)    "
            LOOP
            _DELAY 2
            Writed_Size& = LOF(2)
            confirm$ = MKL$(Writed_Size&) '                          client post WRITED SIZE as control back to Host
            PUT #Client&, , confirm$
            IF Writed_Size& = FileSize& THEN PRINT "Transfer OK!"
        END IF
END SELECT
CLOSE #2, #1, #Host&, #Client&
END


FUNCTION Transfer$ (channel AS LONG, lenght)
    SHARED prubeh
    Transfer$ = ""
    DO
        GET #channel&, , T$
        IF LEN(T$) THEN Transfer$ = Transfer$ + T$
        '  IF _CONNECTED(channel&) = 0 THEN PRINT "Connection failure.": END
    LOOP WHILE LEN(Transfer$) < lenght
END FUNCTION

FUNCTION Network (IP AS STRING)
    Client& = _OPENCLIENT("TCP/IP:3455:" + LTRIM$(IP$))
    IF Client& THEN
        Network = 2 'client
    ELSE
        PRINT "No host found"
        _DELAY 1
        Client& = _OPENHOST("TCP/IP:3455")
        IF Client& THEN
            PRINT "Host created!"
            DO
                i& = _KEYHIT
                IF i& = 27 THEN EXIT FUNCTION
                Host& = _OPENCONNECTION(Client&)
            LOOP UNTIL Host&
            Network = 1
        END IF
    END IF
END FUNCTION

Function Transfer$ show you _CONNECTED using.

ill try it out thanks

Is that both the Client and Host?
line 10 looks like where I set either or but I am not sure what the context should be?

Offline Petr

  • I am instructed.
Hi. Function NETWORK in my program automatically return what current computer is. 1 for host, 2 for client. Program so as is,  is writed for both sides.

Offline Pete

  • Cuz I sez so, varmint!
Hi. Function NETWORK in my program automatically return what current computer is. 1 for host, 2 for client. Program so as is,  is writed for both sides.

What a coincidence. My NETWORK sub designates the host and client computers by numbers 1 and 2 as well; however, I use network mapping instead of tcp/ip to network my office software. I have never tried that on Win 10 but I was able to connect with Visa, XP, and Win 7. That helped, as I did not have to update all my office computers as I bought new ones. I found it necessary to use the LOCK statement to prevent multiple users from accessing the same files at the same time.

Pete

any way to get these file transfer as a sub for example i have been trying for hours to no avail.

Call SendFile(File$) and Call GetFile(File$)

connection is already established as #Connection on server and client programs

Offline Petr

  • I am instructed.
Craz1000: It works well for me. Did you run the program twice to simulate HOST and CLIENT on the same pc?


Offline Pete

  • Cuz I sez so, varmint!
Maybe anti-virus software interfering? I vaguely recall having to disable ZoneAlarm or some sort of modification when I networked my office computers.

Pete

Now that i am finally at my desk. I am trying to put together a library of TCP functions and subs to do various things to be $INCLUDEd in future programs. One of the things i want to add is a file transfer support. What I have on here was where I left off last night. I did copy the entire code that was posted and changed some things to get it to work this way, but nothing is transferred. At the point I left off I was grabbing at straws and the transfer code looks nothing like what was posted above at this point. But you can get the basic idea at what i am trying to do with this file.

Code: [Select]
DIM SHARED BLOCK AS STRING * 4096
DIM SHARED PACKET
PACKET = 4096



SUB GETFILE (FILE$)
    OPEN FILE$ FOR OUTPUT AS #2
    CLOSE #2
    OPEN FILE$ FOR BINARY AS #2
    PRINT "Writing file..."

    CALL SENDMSG("READY")
    DO
        IF CONNECTION THEN
            BLOCK$ = ""
            GET #CONNECTION, , BLOCK$
            PRINT BLOCK$
            IF RTRIM$(BLOCK$) <> ":EOF" THEN PUT #2, , BLOCK$
            CALL SENDMSG("NEXT")
        END IF
    LOOP UNTIL RTRIM$(BLOCK$) = ":EOF"
    CLOSE #2
    PRINT "TRANSFER COMPLETE"
END SUB

SUB SENDFILE (FILE$)
    IF _FILEEXISTS(FILE$) THEN
        OPEN FILE$ FOR BINARY AS #1
    ELSE
        PRINT "File for transfer (source) not found"; FILE$
        EXIT SUB
    END IF

    IF WAITFORREPLY$ = "READY" THEN
        PRINT "Uploading file..."

        DO
            GET #1, , BLOCK$
            PUT #CONNECTION, , BLOCK$
            '    PRINT BLOCK$
            DO
            LOOP UNTIL WAITFORREPLY$ = "NEXT"
            BLOCK$ = ""
        LOOP UNTIL EOF(1)
        CALL SENDMSG(":EOF")
        PRINT "TRANSFER COMPLETE"
        CLOSE #1
    END IF
END SUB

FUNCTION Transfer$ (LENGTH)
    Transfer$ = ""
    DO
        GET #CONNECTION, , T$
        Transfer$ = Transfer$ + T$
    LOOP WHILE LEN(Transfer$) < LENGTH
END FUNCTION


SUB SENDMSG (MSG$)
    MSG$ = UCASE$(MSG$)
    PUT #CONNECTION, , MSG$
END SUB

FUNCTION WAITFORREPLYNUM
    DO
        GET #CONNECTION, , RPL
    LOOP UNTIL RPL <> 0
    WAITFORREPLYNUM = RPL
END FUNCTION

FUNCTION WAITFORREPLYRAW$
    DO
        GET #CONNECTION, , RPL$
    LOOP UNTIL RPL$ <> ""
    WAITFORREPLYRAW$ = RPL$
END FUNCTION


FUNCTION WAITFORREPLY$
    T! = TIMER
    DO
        GET #CONNECTION, , RPL$
    LOOP UNTIL RPL$ <> "" OR TIMER > T! + 3

    IF TIMER > T! + 3 THEN
        WAITFORREPLY$ = "TIMEOUT"
    ELSE
        WAITFORREPLY$ = RTRIM$(RPL$)
    END IF
END FUNCTION
« Last Edit: November 18, 2018, 03:00:42 PM by Craz1000 »

Offline Pete

  • Cuz I sez so, varmint!
I noticed you did not DIM T$.

I got it working tried basing it on the code above again.

Code: [Select]



SUB GETFILE (FILE$)
    PACKET = 4096
    PRINT "Receiving info about file..."
    SENDMSG ("INFO")
    FILESIZE$ = LTRIM$(WAITFORREPLY$)
    FILESIZE& = VAL(FILESIZE$)
    PRINT "File in transfer: "; FILE$
    PRINT "File size (bytes): "; FILESIZE&
    SENDMSG ("OK")

    IF FILESIZE& < PACKET THEN
        BLOCK$ = Transfer$(FILESIZE&)

        OPEN FILE$ FOR OUTPUT AS #2: CLOSE #2
        OPEN RTRIM$(FILE$) FOR BINARY AS #2
        PRINT "Writing file..."
        PUT #2, , BLOCK$
        WROTE& = LOF(2)
        CLOSE #2
        IF WROTE& = FILESIZE& THEN PRINT "Transfer OK!"
    ELSE
        OPEN FILE$ FOR OUTPUT AS #2: CLOSE #2
        OPEN RTRIM$(FILE$) FOR BINARY AS #2
        zbyva& = FILESIZE&

        DO WHILE zbyva& > 0
            IF zbyva& > PACKET THEN BLOCK$ = Transfer$(PACKET) ELSE BLOCK$ = Transfer$(zbyva&)
            zbyva& = zbyva& - PACKET
            PUT #2, , BLOCK$
            SENDMSG ("OK")
            BLOCK$ = ""
        LOOP
        _DELAY 2
        WROTE& = LOF(2)
        CLOSE #2
        IF WROTE& = FILESIZE& THEN PRINT "Transfer OK!"
    END IF
END SUB

SUB SENDFILE (FILE$)
    PACKET = 4096
    IF _FILEEXISTS(FILE$) THEN OPEN FILE$ FOR BINARY AS #1
    PRINT "Sending File name and file size...("; FILE$; " and"; LOF(1); ")"
    IF WAITFORREPLY$ = "INFO" THEN SENDMSG STR$((LOF(1)))

    _DELAY .005

    PRINT "Waiting for confirmation of the name and size ..."

    IF WAITFORREPLY$ = "OK" THEN
        PRINT "Uploading file..."

        zbyva& = LOF(1)
        DO WHILE zbyva& > 0
            IF zbyva& > PACKET THEN Block$ = SPACE$(PACKET) ELSE Block$ = SPACE$(zbyva&)
            zbyva& = zbyva& - PACKET
            GET #1, , Block$ '
            PUT #CONNECTION, , Block$
            IF LOF(1) > PACKET THEN DO UNTIL WAITFORREPLY$ = "OK": LOOP
        LOOP
    END IF
    CLOSE #1
END SUB


FUNCTION Transfer$ (LENGTH&)
    Transfer$ = ""
    DO
        GET #CONNECTION, , T$
        IF LEN(T$) THEN Transfer$ = Transfer$ + T$
        '  IF _CONNECTED(channel&) = 0 THEN PRINT "Connection failure.": END
    LOOP WHILE LEN(Transfer$) < LENGTH&
END FUNCTION


SUB SENDMSG (MSG$)
    MSG$ = UCASE$(MSG$)
    PUT #CONNECTION, , MSG$
END SUB


FUNCTION WAITFORREPLY$
    T! = TIMER
    DO
        GET #CONNECTION, , RPL$
    LOOP UNTIL RPL$ <> "" OR TIMER > T! + 3

    IF TIMER > T! + 3 THEN
        WAITFORREPLY$ = "TIMEOUT"
    ELSE
        WAITFORREPLY$ = RTRIM$(RPL$)
    END IF
END FUNCTION