Recv_() and send_() questions.

Windows specific forum
Ty1003
User
User
Posts: 31
Joined: Thu May 14, 2020 10:31 pm

Recv_() and send_() questions.

Post 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
cas
Enthusiast
Enthusiast
Posts: 597
Joined: Mon Nov 03, 2008 9:56 pm

Re: Recv_() and send_() questions.

Post 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.
User avatar
leonhardt
Enthusiast
Enthusiast
Posts: 220
Joined: Wed Dec 23, 2009 3:26 pm

Re: Recv_() and send_() questions.

Post by leonhardt »

maby mk-soft's network lib is the good choice for you.
viewtopic.php?f=12&t=73882
compiler option: thread safe
poor English...

PureBasic & Delphi & VBA
Ty1003
User
User
Posts: 31
Joined: Thu May 14, 2020 10:31 pm

Re: Recv_() and send_() questions.

Post 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!
Bitblazer
Enthusiast
Enthusiast
Posts: 736
Joined: Mon Apr 10, 2017 6:17 pm
Location: Germany
Contact:

Re: Recv_() and send_() questions.

Post by Bitblazer »

Did you use an UDP connection or a TCP connection?
Ty1003
User
User
Posts: 31
Joined: Thu May 14, 2020 10:31 pm

Re: Recv_() and send_() questions.

Post by Ty1003 »

I think it's just TCP, I just used InitNetwork() and OpenNetworkConnection().
infratec
Always Here
Always Here
Posts: 6867
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Recv_() and send_() questions.

Post 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.
Bitblazer
Enthusiast
Enthusiast
Posts: 736
Joined: Mon Apr 10, 2017 6:17 pm
Location: Germany
Contact:

Re: Recv_() and send_() questions.

Post 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 :)
cas
Enthusiast
Enthusiast
Posts: 597
Joined: Mon Nov 03, 2008 9:56 pm

Re: Recv_() and send_() questions.

Post 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.
Ty1003
User
User
Posts: 31
Joined: Thu May 14, 2020 10:31 pm

Re: Recv_() and send_() questions.

Post 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 :D :D.

// Edit: Code tags were added and the code indentation was corrected (Kiffi)
User avatar
mk-soft
Always Here
Always Here
Posts: 5389
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Recv_() and send_() questions.

Post 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
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Bitblazer
Enthusiast
Enthusiast
Posts: 736
Joined: Mon Apr 10, 2017 6:17 pm
Location: Germany
Contact:

Re: Recv_() and send_() questions.

Post 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.
Ty1003
User
User
Posts: 31
Joined: Thu May 14, 2020 10:31 pm

Re: Recv_() and send_() questions.

Post 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... :(
User avatar
mk-soft
Always Here
Always Here
Posts: 5389
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Recv_() and send_() questions.

Post 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
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
RichAlgeni
Addict
Addict
Posts: 914
Joined: Wed Sep 22, 2010 1:50 am
Location: Bradenton, FL

Re: Recv_() and send_() questions.

Post by RichAlgeni »

Did you get your server to work correctly Ty1003?
Post Reply