Jump to content
Sign in to follow this  
Ontosy

TCPRecv truncated

Recommended Posts

Ontosy

I have:

$TCPRecv = TCPRecv($RouterIP, 2048)

but $TCPRecv return truncated at 1461 characters.

May depend on what?

Share this post


Link to post
Share on other sites
qsek

Maybe just guessing here but there could be a 0x00 binary character in the output. Depends on what you do with the output and how you track it. Cant say anything without more code, at least a small reproducer.

Edited by qsek

Teamspeak 3 User Viewer - Quick and functional TS3 Query script, which shows online users.Cached Screenshot Deleter - Deletes older Fraps Screenshots if they exceed a specified limit.Unresolved Topics:Intercept and modify dragdrop text behaviour in scite

Share this post


Link to post
Share on other sites
subzerostig

Also the tcp functions can only handle a certain amount(pretty certain). If it isn't what qsek said then you could explore that possibility and probably have to send in packets.


There are 10 types of people in this world. Those that understand binary, and those that do not

Share this post


Link to post
Share on other sites
Kealper

I've come across this problem myself... The problem is that TCPRecv is a non-blocking function, meaning it will return what data it has received so far instead of waiting for all of it, and since TCP is a stream-based protocol, there is no way for it to determine if your application's packet has been fully read by itself.

Because of those two things I mentioned, what is happening is that when you call TCPRecv, it is only returning the data that has been sent to it so far (because sending data over a network is actually not instantaneous, it is just really fast). To fix this, you need to implement a receive buffer in your program. The buffer would temporarily hold the received data until your application has determined that the whole packet it is looking for has arrived.

If speed is not an issue, the easiest way would just be to throw like a Sleep(100) in just above the TCPRecv call, giving your program just a bit more time to receive all of the data before you go to read it. This has it's drawbacks because it still has some corner-cases where it won't return all of the data, but it should fix most of them.

If speed is an issue, then a more complex buffering system would have to be made...And I wouldn't mind helping with that if you were unable to figure out how to go about doing it. ;)

EDIT: Also forgot to mention that it isn't a problem with receiving null characters, the TCP functions don't seem to be null-terminated from my experience.

SECOND EDIT: I whipped together a simple example to show what I mean by a receive buffer. This is a very basic "echo" server which listens for telnet connections, and when it gets them, it will echo back any message that you type as soon as you press the enter key. If you are using Microsoft's telnet client, this example will show exactly what I mean, since Microsoft's telnet client sends out letters as you type them.

TCPStartup()

Global $Listen = TCPListen("0.0.0.0", 1234) ;Listen on all addresses on port 1234
If @error Then ;Uh-oh!
    ConsoleWrite("Error! Couldn't listen for clients on port 1234! Is another instance of this example already running?" & @CRLF)
    Exit 1 ;Exit with error-code 1
EndIf

While 1
    Local $iSock = TCPAccept($Listen) ;Check for new connections
    If $iSock = -1 Then ContinueLoop ;If no new connections are present, go back to the top of the loop and check again
    ConsoleWrite("A new client has connected!" & @CRLF) ;A wild connection appears!
    Local $sBuffer = "" ;Create a local receive buffer variable
    While 1 ;Go in to a loop to read everything the client sends in to the buffer
        Local $sRecv = TCPRecv($iSock, 512) ;Write up to 512 characters at a time in to the buffer
        If @error Then ;If the client disconnected, stop right here and check for new clients again
            ConsoleWrite("Client has disconnected. Now waiting for more clients..." & @CRLF)
            ExitLoop
        EndIf
        If $sRecv = "" Then ContinueLoop ;Client sent no data, go check again...
        $sBuffer &= $sRecv ;Client did send data, throw this new data in to the buffer
        ConsoleWrite("Client sent: " & $sRecv & @CRLF)
        If StringInStr($sBuffer, @CRLF) Then ;If the client has sent an @CRLF (an enter button press), then do this
            TCPSend($iSock, "received: " & $sBuffer & @CRLF) ;Send their message they sent back to them
            $sBuffer = "" ;Empty the temporary buffer and start waiting for more data
        EndIf
    WEnd
WEnd
Edited by Kealper
  • Like 1

Share this post


Link to post
Share on other sites
Ontosy

the easiest way would just be to throw like a Sleep(100) in just above the TCPRecv call

ty ;)

Share this post


Link to post
Share on other sites
Kealper

Glad to be of assistance! ;)


Share this post


Link to post
Share on other sites
sanfrancrisko

Sorry to reactive this somewhat dead thread...

I'm having an issue with trying to implement the TCPRecv() function in a script to listen for a (relatively) large file transfer.

The "sender" will alert the "receiver" about how many bytes it should expect to receive via a config file on a file share (no extra bytes can go across the line except for the binary file transferred, unfortunately). The receiver then enters this loop:

Do
$receivedFileChunk &= TCPRecv($connectedSocket, $receiveWindow, 1)
$totalReceivedBytes = BinaryLen($receivedFileChunk)
logwrite($totalReceivedBytes)
until $totalReceivedBytes = $fileSize

The problem is, the CPU spikes to 100% and the file write is incredibly slow to disk. I think the Do...Until is in such a tight loop that it's calling the TCPRecv() function so rapidly and only lifting a few bytes at a time.

Problem is, for the life of me, I cannot figure out a way to solve this. Adding a sleep in to the loop doesn't do anything, it just slows everything down. If TCPRecv() could be a blocking function it would solve all my problems! :)

Previously, I had the sender splitting the file in to even chunks, alerting the receiver as to the chunk size and how many there'd be, then a for loop iterated on the receiver for as many chunks as there were, concatenating the chunks to the file. Code here:

I may just return to that method, but if anyone could suggest a way working, it would be greatly appreciated! This is definitely the better way to do it...if it works!

Edited by sanfrancrisko

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×