Very stupid network question :-p

Everything else that doesn't fall into one of the other PB categories.
KarLKoX
Enthusiast
Enthusiast
Posts: 681
Joined: Mon Oct 06, 2003 7:13 pm
Location: France
Contact:

Very stupid network question :-p

Post by KarLKoX »

Hi, i ve a very stupid bug : i took the server/client network examples and instead of sending a string, i decided to send a struct.
To begin, i tried with a minimalist struct wich have the connexion ID and a simple message.
The client send this struct to the server wich receive the id and the message but i always get a corrupted string ! (the id is good)
I tried differents solutions : allocate memory for the string (allocatememory, space ...), use of the copymemory(string, struct\message, len(string)) without success.
Here is the client part :

Code: Select all

Structure POUET
  id.l
  msg.s
EndStructure

If InitNetwork() = 0
  MessageRequester("Error", "Can't initialize the network !", 0)
  End
EndIf

Port = 6832

ConnectionID = OpenNetworkConnection("127.0.0.1", Port)
*p.POUET = AllocateMemory(SizeOf(POUET))
If *p = 0
  MessageRequester("Error", "Memory allocation failed !")
  End
EndIf
*p\id = ConnectionID
*p\msg = "pouet"+Chr(0)

If ConnectionID
  MessageRequester("PureBasic - Client", "Client connected to server...", 0)
  
  SendNetworkData(ConnectionID, *p, SizeOf(POUET) )
    
  MessageRequester("PureBasic - Client", "Data has been sent to the server, please check it before quit...", 0)
  
  CloseNetworkConnection(ConnectionID)
Else
  MessageRequester("PureBasic - Client", "Can't find the server (Is it launched ?).", 0)
EndIf

FreeMemory(*p)
End   
And here is the server part :

Code: Select all

Structure POUET
  id.l
  msg.s
EndStructure

If InitNetwork() = 0
  MessageRequester("Error", "Can't initialize the network !", 0)
  End
EndIf

Port = 6832

If CreateNetworkServer(Port)

  MessageRequester("PureBasic - Server", "Server created (Port "+Str(Port)+").", 0)
  
  Repeat
      
    SEvent = NetworkServerEvent()
  
    If SEvent
    
      ClientID = NetworkClientID()
  
      Select SEvent
      
        Case 1
          MessageRequester("PureBasic - Server", "A new client has connected !", 0)
  
        Case 2
          MessageRequester("PureBasic - Server", "Client "+Str(ClientID)+" has send a packet !", 0)
          *p.POUET = AllocateMemory(SizeOf(POUET))
          numbytes = ReceiveNetworkData(ClientID, *p, SizeOf(POUET) )
          MessageRequester("Info", "numbytes (should be sizeof(POUET) ) : " + Str(numbytes) + " ID : "+ Str(*p\id) + " MSG : "+ *p\msg, 0)
  
        Case 3
          MessageRequester("PureBasic - Server", "Client "+Str(ClientID)+" has send a file via the network !", 0)
          ReceiveNetworkFile(ClientID, "C:\TEST_Network.ftp3")
  
        Case 4
          MessageRequester("PureBasic - Server", "Client "+Str(ClientID)+" has closed the connexion...", 0)
          Quit = 1
    
      EndSelect
    EndIf
    
  Until Quit = 1 
  
  MessageRequester("PureBasic - Server", "Click to quit the server.", 0)
  
  CloseNetworkServer()
Else
  MessageRequester("Error", "Can't create the server (port in use ?).", 0)
EndIf

  
End   
It should be a very stupid bug but this is my first network code with PB :-p
Thanx for reading :)
"Qui baise trop bouffe un poil." P. Desproges

http://karlkox.blogspot.com/
Nik
Addict
Addict
Posts: 1017
Joined: Fri May 13, 2005 11:45 pm
Location: Germany
Contact:

Post by Nik »

Lets say with the current pb networking is somewaht complicated. the problem is taht the string gets splitted this can mean the following things:
a) More then one Sting in one receive buffer e.g.
Buffer1:String1|String2

b) A sting can be splitted over more than one buffer e.g.
Buffer 1: Part1 of String 1
Buffer 2: Part2 of string 1
Buffer 3: Part3 of String 1

c) A mixture of a) and b)
Buffer 1: Part 1 of String 1
Buffer 2: Part 2 of String 1 | Part 1 of String 2
Buffer 3: Part 2 of String 2

You will never know how long the parts are this seems to be near to random. You never know if it will happen at all. You know that if you test weather SendNetworkDatas() return is > than 0 everything will be tranmsferred and that the order is correct.

I think this is everything you will need to build an algorith if you don't get it to work ask and I will help you a bit more. 8)

:arrow: This is not stupid at all it's one of the biggest flaws of PB besides you can't do threaded networking. But it's possible to get around it with a good algoprithm.
@Fred if you are interrested in my solution don't bother to ask
KarLKoX
Enthusiast
Enthusiast
Posts: 681
Joined: Mon Oct 06, 2003 7:13 pm
Location: France
Contact:

Post by KarLKoX »

Ok, i understand better how networking works, i think i ll use a opensource lib (this should be enough) wich can resolve my problem quickly :)
Thanx :)
"Qui baise trop bouffe un poil." P. Desproges

http://karlkox.blogspot.com/
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Post by Rescator »

Hmm!

Structure POUET
id.l
msg.s
EndStructure

is the same as i.e:

Structure POUET
id.l
msg.l
EndStructure

as msg.s is just a long that has the pointer to where the string actualy is.

So when you pass along the structure, you only pass along the id and the memory pointer to the string,
but the string is never passed along.

So you have to make your own kind of packets for the structures.

I.e. (just a simple/quick example)

size=SizeOf(#Long)+SizeOf(#Long)+Len(*p\msg)+1
*mem=AllocateMemory(size)

PokeL(*mem+4,*p\id) ;id
PokeL(*mem+8,Len(*p\msg)) ;length of string
CopyMemory(*p\msg,*mem,Len(*p\msg))
PokeB(*mem+12+Len(*p\msg),0) ;0 terminator for string

This is really the only way to make sure everything in a structure is passed along.
(wether it is saving a structure to disk, or across a network)
Obviously with networking there is other issues, like the possibility of split packets due to very long strings as Nik mentioned.

Make sure you check the result returned by the send and recieve network data functions.

As in this example. you would know the first 4 bytes is the structure id,
the next 4 bytes is the length of the string,
due to this you know that there should be string length + 1 (the 0 terminator) of data left.
if the first chunk of data received is smaller than the expected length,
and receivenetworkdata returns a result that is equal to your receive buffer, then keep reading until it is less or 0 bytes. (see ReceiveNetworkData() in PB help)

Sorry I didn't have time to make a full example for you, but hopefully it made some sense at least :)

PS! Since you send along info of string length, and also add a 0 terminator (not really needed, but good practice to avoid issues with broken strings etc.)
you always know how much data is being sent,
so even if you get 2 structures, where 1 and a half fits into your receive buffer, you can easily parse/see that the 2nd structure is split in two.

Also with bigger structures that has multiple strings,
you should also make sure to pass along the total size of the structure itself, so you can easily see if the structure is split or not.
Another tip is to add a checksum to the data sent,
so that you can do a quick checksum test after you have joined a split structure back together,
to make sure you joined them correctly.
Nik
Addict
Addict
Posts: 1017
Joined: Fri May 13, 2005 11:45 pm
Location: Germany
Contact:

Post by Nik »

Rescator is right...
But I think one thing isn't right, he say
first chunk of data received is smaller than the expected length,
and receivenetworkdata returns a result that is equal to your receive buffer
But I found that the splitting happens much earlier than the buffers size...
You instead should make sure (also mentioned bei Recator) to only read the data form your buffer wher the length is thre return value of receive network data.. And then you can try to read out the structure within the buffer using the length you put into the buffer...
KarLKoX
Enthusiast
Enthusiast
Posts: 681
Joined: Mon Oct 06, 2003 7:13 pm
Location: France
Contact:

Post by KarLKoX »

Thanx for your help, i finally understood how all the thing works, i thought network programming was easier but never mind :)
"Qui baise trop bouffe un poil." P. Desproges

http://karlkox.blogspot.com/
Post Reply