Feature request > Network

\0 terminated SOCK_RECV command

<< < (2/3) > >>

Kitty Hello:
OK. Here's what I think about that. I have no idea if I'm right:
- You send data to another computer.
  - I send() as much of that as I can send.
  - if there's more data, I send again and again

- You read from a socket
  -I read until the other end either disconnects, or there is nothing more to read (EWOULDBLOCK)

Can anyone shed light on this? Ocean, maybe?


Moru:
One thing I have always wondered about is if my app sends data very fast in small packets, will I still get the packets one at a time when I read from the socket or will they be concatenated on the way and sent as one packet? I was using some library for Visual Basic a few years ago and in the documentation it said not to expect the packets to stay separated, they could get concatenated in transfer. You had to put your own start packet/end packet codes into your packets.

About the original question, a packet is binary data, I don't think it should stop reading on 0, you should read until EOF or similar.

Moru:
I have tested this long time ago (before the new net commands) and there was no need for zero-termination. I used \0 as split between command and parameters instead since glbasic don't terminate a string on ascii 0. Only thing that is important is the length of the string, just as it's supposed to be in basic. Zero-termination is just there for compatibility with inline C I guess?

Kitty Hello:
OK, I got enlightened now.

When you send strings (long ones) over the internet, usually you provide some sort of "header" for you data. That means, you read 4 bytes that describe the length of the coming package, and then read this length from the socket, checking for errors (connection broken e.g.)

If you read from a website or so, the thing acts differently. They have a sort of EOF by disconnecting after the sending. The server will send you the full page and then close its socket. That way you know that your data was received completely.

For fast interchange, I'd suggest going route #1. That's BTW the thing I do with the NETSENDMSG commands.

Did I miss a thing?

FutureCow:
Here's a test program with some interesting results

NOTE: Compile as a console program then run 2 copies of it.

--- Code: (glbasic) ---GLOBAL Net_ServerIP$
GLOBAL EstablishedConnection
GLOBAL Net_SocketNumber
GLOBAL Done
Net_SocketNumber=1234
Net_ServerIP$="127.0.0.1"

SOCK_INIT()

// MAIN
//-------------------------------------------------------------------------
Done=0

STDOUT "Press 1 to be server\n"
STDOUT "Press 2 to be client\n"

LOCAL Result$=INKEY$()
IF Result$ = "1" // pressed 1
STDOUT "Server\n"
DEBUG "Server-debug\n"
GOSUB server
ELSEIF Result$= "2" // pressed 2
STDOUT "Client\n"
DEBUG "Client-debug\n"
GOSUB Client
ENDIF


//-------------------------------------------------------------------------
SUB server:
LOCAL Done=0
LOCAL ClientIPAddress%
LOCAL Sock%
STDOUT "Waiting for connection...\n"

Sock=SOCK_TCPLISTEN(Net_SocketNumber) // Listen for connections on our socket

WHILE Done=0
EstablishedConnection=SOCK_TCPACCEPT(Sock,ClientIPAddress) // Check for established client connection
IF EstablishedConnection > 0 THEN Done=1 // If a connection was successful
WEND

// We now have a connection

SOCK_TCPSEND(EstablishedConnection,"1")
SOCK_TCPSEND(EstablishedConnection,"2\0")
SOCK_TCPSEND(EstablishedConnection,"3"+CHR$(0))
SOCK_TCPSEND(EstablishedConnection,"4")
SOCK_TCPSEND(EstablishedConnection,"5\0")
SOCK_TCPSEND(EstablishedConnection,"6"+CHR$(0))

DEBUG ("Server Done\n")
SLEEP 10000
ENDSUB

//-------------------------------------------------------------------------
SUB Client:
LOCAL Done=0
LOCAL ReturnCode
LOCAL ReceivedMessage$
LOCAL YLoc=50

STDOUT "Establishing connection with "+Net_ServerIP$+" on port "+Net_SocketNumber+"...\n"
EstablishedConnection=SOCK_TCPCONNECT(Net_ServerIP$,Net_SocketNumber) // Try to connect to server
IF EstablishedConnection = -1 // Failure
STDERR "Network error : client failed to create connection"
END
ENDIF

SLEEP 500 // allow messages to cache
LOCAL Done=0
WHILE Done=0
ReturnCode=SOCK_RECV(EstablishedConnection, ReceivedMessage$, 1023)
IF ReturnCode=0
STDERR "Remote end has disconnected\n"
END
ELSEIF ReturnCode=-1
STDERR "Network error has occurred"
STDERR "Error received was : "+NETGETLASTERROR$()+"\n"
END
ELSEIF ReturnCode=-2 // Nothing waiting in the queue
Done=1
ELSE
DEBUG "Message length received : "+ReturnCode+"   Message recieved = " + ReceivedMessage$ + "\n"
STDOUT "Message length received : "+ReturnCode+"   Message recieved = " + ReceivedMessage$ + "\n"
ENDIF
WEND
SLEEP 10000
ENDSUB


--- End code ---

What you will see is that the client receives only one message - the output from the client is

--- Code: (glbasic) ---Message length received : 8   Message recieved = 123
--- End code ---

4,5 and 6 don't appear, as the CHR$(0) terminates the printing of the string, but you can tell by the message length (8 characters) that all the data was sent, then returned by one SOCK_RECV() command.

From everything I've found doing an internet search, it appears that all characters (including \0) should be sent with send() or recv() - the use of the NUL character as a message delimeter would be entirely a user implementation issue.

From what you wrote Gernot I assume that NETGETMSG and NETSENDMSG are appending a \0 and doing a SPLITSTR to separate the messages?

Navigation

[0] Message Index

[#] Next page

[*] Previous page

Go to full version