; How to send and receive Strings via network correctly ; The Send-Routine is quite simple ; You should use a threads to send datas, espacially on the server to avoid blockings. ; Here is nothing special but I will try to explain every line. Procedure SendString(id,txt$) ; connected Socket, string$ ; calculate bufferlength length.l=Len(txt$)+1 ; String + EOL length.l+4 ; Packet length at beginning length.l+4 ; CRC32 *mem.l=GlobalAlloc_(#GMEM_FIXED | #GMEM_ZEROINIT, length.l) ; Allocate needed memory PokeL(*mem.l,length.l) ; Store the Header (Size of Packet) PokeS(*mem.l+4,txt$) ; Store String (Datas) crc.l=CRC32Fingerprint(*mem.l+4,length.l- ; Create CRC32 Checksum - Not really needed PokeL(*mem.l+length.l-4,crc.l) ; Store it at the end of the packet Repeat ; Loop for Datasend send=send_(id,*mem.l,length,0) ; Send our Datas sended+send ; Count our sended Bytes If send=#SOCKET_ERROR ; Check for socket error wsaerror=WSAGetLastError_() If wsaerror=#WSANOTINITIALISED:err$="Wsa not initialized":EndIf If wsaerror=#WSAENETDOWN :err$="The Windows Sockets implementation has detected that the network subsystem has failed.":EndIf If wsaerror=#WSAENOTCONN :err$="Socket not connected.":EndIf If wsaerror=#WSAEINTR :err$="The (blocking) call was canceled using WSACancelBlocking":EndIf If wsaerror=#WSAEINPROGRESS :err$="A blocking Windows Sockets operation is in progress.":EndIf If wsaerror=#WSAENOTSOCK :err$="The descriptor is not a socket.":EndIf If wsaerror=#WSAEOPNOTSUPP :err$="MSG_OOB was specified, but the socket is not of type SOCK_STREAM.":EndIf If wsaerror=#WSAESHUTDOWN :err$="The socket has been shut down; it is not possible to recv on a socket after shutdown has been invoked with how set to 0 or 2.":EndIf If wsaerror=#WSAEMSGSIZE :err$="The datagram was too large to fit into the specified buffer and was truncated.":EndIf If wsaerror=#WSAEINVAL :err$="The socket has not been bound with bind.":EndIf If wsaerror=#WSAECONNABORTED :err$="The virtual circuit was aborted due to timeout or other failure.":EndIf If wsaerror=#WSAECONNRESET :err$="The virtual circuit was reset by the remote side.":EndIf If wsaerror=#WSAEWOULDBLOCK :err$="The socket is marked as nonblocking":EndIf ; This is VERY importend to check for. ; If the TCP/IP Buffer is full and your datas can not send as fast as your app it sends, you get ; this error messages. You have to send your datas again and again till its complete. ; There is another methode too, but I think this is the easiest way. If wsaerror=#WSAEWOULDBLOCK:send=0:sended=0:Delay(25):EndIf EndIf ; Errorcheck Until sended>=length Or send=#SOCKET_ERROR ; Loop as long as all Datas has been send GlobalFree_(*mem) ; Free our Memory again EndProcedure ; The following receive-code receives a string that is send with my send procedure above. ; I make it a little bit shorter as the normal one in our app couse that is MUCH bigger. ; Short explanation to the variables: ; totalreceived -> amount of datas that are allready received on the buffer ; receiveexpected -> The expected Size of the sended String ; ; The Datapackage is send in the following shema: ; ; Packetsite.l -> 4 Bytes Packetsize ; string$ -> unknown length, chr(0) terminated ; CRC32 -> optional a CRC32 at the end (not realy needed) ; ; HOW TO USE: ; The receive routine should only be called if an networkevent on this socket is received. ; The code shown here is only to handle one user, that means you can only use it on a clients side. ; If you want to use it on server side you will need a buffer for every user connected. ; The vars Totalreceived.l and receiveexpected.l should be in a list for every user too. ; ; After connecting to a server you have to catch incoming events you have to wait for. ; Use WSAAsyncSelect_() to do this. Its easy to use. Add the flags FD_Read to it. Thats all you need. ; Now you can use WaitWindowEvent() for waiting for network events too. ; ; Dont forget to initialize the network and allocate the *receivebuffer to eg 10000 Bytes first. ; Should be enough but depends on you stringsize. ; here we go... ; --->>> RECEIVEROUTINE <<<--- If receiveexpected>0 ; We allready know our Packetsize, so we can receive it received=recv_(serversocket.l,*receivebuffer.l+totalreceived.l,receiveexpected-totalreceived,0) ; Receive and attach the datas to our buffer If received<>#SOCKET_ERROR ;WSA Error detected? No? Then.... If received>0:totalreceived+received:EndIf ;add the received bytes to our Bytecounter in totalreceived If totalreceived=PeekL(*receivebuffer.l) ; Is our packet complete? command$=PeekS(*receivebuffer+4) ; Get our String from Memorybuffer +4 (couse 0 is packetsize) totalreceived=0 ; Datapacket complete, reset value and wait for new one receiveexpected=-1 ; Wait for new packetheader but do not execute the next part! EndIf Else ; YOUR ERRORHANDLING HERE EndIf EndIf If totalreceived<3 And receiveexpected=0 ; Receive our Packetheader till it is complete received=recv_(serversocket.l,*receivebuffer+totalreceived,4-totalreceived,0) ; Receive TCP/IP Buffer (max. 4 Bytes) If received<>#SOCKET_ERROR If received=4:receiveexpected=PeekL(*receivebuffer):EndIf ; Completed yet? If received>0:totalreceived+received:EndIf ; Count our Received bytes (we need 4!) EndIf ; Your Errorhandling here EndIf If receiveexpected=-1:receiveexpected=0:EndIf ; This is only to avoid receiving datas that has to wait in the queue ; Until the next event is processed ; ExecutableFormat= ; EOF