Page 1 of 1
Recv_() and send_() questions.
Posted: Fri Oct 23, 2020 4:32 am
by Ty1003
So I have an application that uses networking, E.G., initNetwork(), NetworkServerEvent() etc etc. However, I am having issues with Packet mixing. E.G., if two packets are sent at the same time, the text get scrambled together. I tried to solve it with a delay but this makes it lag, for quite obvious reasons. I heard about recv_() and send_(), and tried to add them, but from the looks of it, I would have to rewrite my entire client/server to use these. Is this really the best rout? Is there another way on Windows to make packet mixing not happen?
Thanks
Re: Recv_() and send_() questions.
Posted: Fri Oct 23, 2020 10:14 am
by cas
If i understand correctly, you are sending in multiple threads at the same time and you are using global buffer? To solve this, you must allocate local buffer for each thread or use mutex.
Re: Recv_() and send_() questions.
Posted: Fri Oct 23, 2020 11:23 am
by leonhardt
maby mk-soft's network lib is the good choice for you.
viewtopic.php?f=12&t=73882
compiler option: thread safe
Re: Recv_() and send_() questions.
Posted: Fri Oct 23, 2020 2:16 pm
by Ty1003
Okay,
Firstly, no, the issue is if more than one packet is sent at aaround the same time, the text from them gets mashed.
And second, I'll take a look at that lib.
Thanks all for the suggestions!
Re: Recv_() and send_() questions.
Posted: Fri Oct 23, 2020 5:40 pm
by Bitblazer
Did you use an UDP connection or a TCP connection?
Re: Recv_() and send_() questions.
Posted: Fri Oct 23, 2020 8:22 pm
by Ty1003
I think it's just TCP, I just used InitNetwork() and OpenNetworkConnection().
Re: Recv_() and send_() questions.
Posted: Fri Oct 23, 2020 10:31 pm
by infratec
This is a coding question.
So write a small (working) version of your code and show it in this section.
Something with your receive code is wrong.
Every packet come on its own and since the client is known, it can not mixed up.
(If it is handled correct). API functions changes nothing on the receive logic.
Re: Recv_() and send_() questions.
Posted: Sat Oct 24, 2020 11:32 am
by Bitblazer
Ty1003 wrote:I think it's just TCP, I just used InitNetwork() and OpenNetworkConnection().
If you used
OpenNetworkConnection, the default connection mode will be TCP. The order with TCP will be maintained, so the problem is in your code. Show your implementation, so we can help
Re: Recv_() and send_() questions.
Posted: Sat Oct 24, 2020 2:11 pm
by cas
Ty1003 wrote:Okay,
Firstly, no, the issue is if more than one packet is sent at aaround the same time, the text from them gets mashed.
And second, I'll take a look at that lib.
Thanks all for the suggestions!
Please, at least, since you are not providing example code that shows your problem, provide an example of "mashed" data.
For example, if you send 2 packets
packet1: "abcd"
packet2: "1234"
and you receive "abcd1234" in a single read but you want to receive each of them separately then you must add a header to each network packet that indicates its size if packets do not have fixed size. If all packets are fixed size then you can specify number of bytes to read when you receive them.
Re: Recv_() and send_() questions.
Posted: Sat Oct 24, 2020 2:35 pm
by Ty1003
Alright, here are the networking parts of my code. I took out the gadget and sound playing bits, as I don't think they would effect it at all.
Server
Code: Select all
Global NewMap Users.S()
#MSG_WAITALL=$8
Declare Main()
Procedure Main()
OpenConsole("Talk Server.")
InitNetwork()
Protected Port=6832
Delay(50)
If CreateNetworkServer(0,Port)
PrintN("Server created (Port "+Str(Port)+").")
If ReadFile(0,"MOTD.txt")
Protected MOTD.S=ReadString(0)
EndIf
Repeat
Protected SEvent=NetworkServerEvent()
If SEvent
Protected ClientID=EventClient()
Select SEvent
Case #PB_NetworkEvent_Connect
ID=ClientID
PrintN(""+ID+" has connected !")
Case #PB_NetworkEvent_Data
*Buffer=AllocateMemory(1000)
recv_(ClientID,*Buffer,1000,#MSG_WAITALL)
ID=ClientID
Protected PeekedMem.S=""
PeekedMem=PeekS(*Buffer,-1,#PB_UTF8)
Debug PeekedMem
If Left(PeekedMem,1)="@"
Protected Name.S=Mid(PeekedMem,2)
Users(Str(ID))=Name
Protected MOTDString.S="@MOTD "+MOTD
send_(Val(MapKey(Users())),@MOTDString,StringByteLength(MOTDString),#Null)
recv_(ID,*Buffer,1000,#MSG_WAITALL)
Protected NameString.S=Name+" has connected"
ForEach Users()
send_(Val(MapKey(Users())),@NameString,StringByteLength(NameString),#Null)
Next
Else
If FindMapElement(Users(),Str(ID))
Protected Chat.S=Users()+": "+PeekedMem
PrintN(Chat)
ForEach Users()
send_(Val(MapKey(Users())),@Chat,StringByteLength(Chat),#Null)
Next
EndIf
EndIf
FreeMemory(*Buffer)
Case #PB_NetworkEvent_Disconnect
ID=ClientID
PrintN(""+ID+" has disconnected !")
EndSelect
EndIf
ForEver
CloseNetworkServer(0)
Else
PrintN("Can't create the server (port in use ?).")
EndIf
EndProcedure
Main()
And client
Code: Select all
InitNetwork()
Protected Port=6832
Protected Name.S=InputRequester("Name","Please enter your name.","")
If Name=""
End
EndIf
Protected ConnectionID=OpenNetworkConnection("127.0.0.1",Port)
If ConnectionID
send_(ConnectionID,@Name,StringByteLength(Name),#Null)
Protected TempName.S="@"+Name
send_(ConnectionID, @TempName,StringByteLength(TempName),#Null)
Repeat
Protected SEvent=NetworkClientEvent(ConnectionID)
Select SEvent
Case #PB_NetworkEvent_Disconnect
ConnectionID=0
PlaySound(Disconnect)
Break
Case #PB_NetworkEvent_Data
If ConnectionID=0
Break
EndIf
Protected *Buffer=AllocateMemory(1000)
recv_(ConnectionID,*Buffer,1000,#MSG_WAITALL)
Protected Message.S=PeekS(*Buffer,-1,#PB_UTF8)
If FindString(Message,": ")=0
If FindString(Message,"has connected")<>0
PlaySound(Online)
ElseIf Left(Message,5)="@MOTD"
Message=Mid(Message,6)
EndIf
Else
PlaySound(Chat)
EndIf
AddGadgetItem(#History_List,-1,Message)
FreeMemory(*Buffer)
EndSelect
Protected Event=WaitWindowEvent(1)
Select Event
Case #PB_Event_Menu
Select EventMenu()
Case #Send
If GetActiveGadget()=#Chat_Field
Protected Content.S=GetGadgetText(#Chat_Field)
If Content=""
PlaySound(Empty)
Continue
Else
SendNetworkString(ConnectionID,Content,#PB_UTF8)
SetGadgetText(#Chat_Field,"")
PlaySound(Send)
EndIf
EndIf
EndSelect
Case #PB_Event_Gadget
Select EventGadget()
Case #Exit_Button
CloseNetworkConnection(ConnectionID)
End
EndSelect
EndSelect
ForEver
EndIf
That is missing the gadget and sound loading/playing code, but you should be able to get the idea. The problem I was having was with mixing packets, and so I tried switching to send_() and recv_() from the WinAPI, but now nothing gets sent at all
.
// Edit: Code tags were added and the code indentation was corrected (Kiffi)
Re: Recv_() and send_() questions.
Posted: Sat Oct 24, 2020 6:39 pm
by mk-soft
TCP/IP only takes care of this with a handshake, which allows data up to 64 KB to be sent and received in packets in the correct order. ISO model layer 4.
This means that the data is transmitted piece by piece as packets (local network approx. 1500 byte, Internet a little less approx. 1492 byte)
Your data which is sent and received is in the ISO model layer 5 to 7 and you have to take care of the content yourself, you also have to take care of the protocols like http(s) FTP, etc.
SendNetworkData only enters the data for sending into the send buffer and ReceiveNetworkData only fetches the data already received into the receive buffer.
If all packets have arrived in the whole large (up to 64 kb), you have to check yourself, because it is possible that a part of the data has already arrived
This also means that if you call SendNetwork twice, all data will be available when the receive buffer is queried.
Common methods of transmitting data is to use a header (for example, Modbus/TCP),
Work with control characters (StartOfText #STX$, EndOfText #ETX$),
or
As with HTTP in Text Header to include the size of the data
Re: Recv_() and send_() questions.
Posted: Sat Oct 24, 2020 7:40 pm
by Bitblazer
Why do you use a wild mix of purebasic network library and api calls?
That can create 'interesting' problems due to internal buffering. It could be interesting to trace what actually happens in such a case with
wireshark and
WinApiOverride. Basically the network api sequence might be different to what you think it is. Try using only the purebasic network functions first.
Re: Recv_() and send_() questions.
Posted: Sat Oct 24, 2020 8:05 pm
by Ty1003
Hi.
Initially, I did use just PB calls. But the MOTD and online packet, for example would get mashed. Or if two users sent a chat at the same time. So I tried using recv_() and send_() to insure the packet arrives before sending the next one, but it doesn't work...
Re: Recv_() and send_() questions.
Posted: Sat Oct 24, 2020 9:01 pm
by mk-soft
Not read what I have written?
The same applies to API Send and Receive
Here an example with short text sending over UDP and control character STX, ETX
Link:
viewtopic.php?f=12&t=74200
Re: Recv_() and send_() questions.
Posted: Mon Nov 30, 2020 11:10 pm
by RichAlgeni
Did you get your server to work correctly Ty1003?