need help on server threads...

Just starting out? Need help? Post your questions and find answers here.
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by ricardo.

Im trying to send/receive some files using some threads.
After a small battle betewn mi PC and i, im making some advance, but im in one point that i can understand what is failing... its 3:30 a.m. maybe my brain dosent work anymore.
Please take a look and see if you can see what im doing wrong.

There are 2 procedures, one for every app (one for the client and one for the server) and both are working now on the same PC, that why both are calling to the same files.

This procedure runs everytime i click a button and its suppoused to send some file (a1.mp3, a2.mp3, a3.mp3, etc) to the server, i want to receive several files at the same time.
The index are the port of the server, cause every thread procedure on the server side has a different port (maybe there some oher way to do it)

Procedure EnviaFile(index.l)
Cont.l = Cont + 1 ; global
Buffer = AllocateMemory(Cont, FileSize("a" + str(cont) + .mp3"), 0)
OpenFile(Cont,"a"+ Str(Cont)+".mp3")
ReadData(Buffer,FileSize("a"+ Str(Cont)+".mp3"))
CloseFile(Cont)
ConnectionID = OpenNetworkConnection("127.0.0.1", (index))
If ConnectionID
SendNetworkData(ConnectionID, Buffer, FileSize("a"+ Str(Cont)+".mp3"))
CloseNetworkConnection(ConnectionID)
;FreeMemory(Cont)
EndIf
EndProcedure


;SERVER SIDE PROCEDURE
This one receives a1.mp3 and writes b1.mp3, etc.

Procedure RecibeFile(Index.l)
Result = CreateNetworkServer(Index)
Cont.l = cont + 1 ;global
Repeat
ServerEvent.l = NetworkServerEvent()
If ServerEvent
Select ServerEvent
Case 2
ClientID = NetworkClientID()
If FindString(IDClient,"*" + Str(cont) + "*",0) = 0; dirty
IDClient = IDClient + "*" + Str(cont) + "* "
Buffer = AllocateMemory(Cont, FileSize("a"+ Str(Cont)+".mp3"), 0)
ReceiveNetworkData(ClientID, Buffer, FileSize("a"+ Str(Cont)+".mp3"))
OpenFile(Cont,"b"+ Str(Cont)+".mp3")
WriteData(Buffer,FileSize("a"+ Str(Cont)+".mp3"))
CloseFile(Cont)
CloseNetworkConnection(Result)
;FreeMemory(Cont)
Conectado.l = 1
EndIf
Case 4
CloseNetworkConnection(Result)
Conectado.l = 1
EndSelect
EndIf
Until Conectado = 1
EndIf
EndProcedure

The result i that i can send/receive apparentely 3 or more files, but writes always the same one.
I make the DIRTY trick because the ServerEvent is received on every thread no matter if its originated on the server connected to another thread and since im using only one client the ClientID is the same too, then i make this dirty trik to know if the event comes from one thread different from this one.

When the server receives some text message, it run s the procedure with a new thread and replay to the client the number of the port recently opened and the waits until getting the file.
And seems to work, create a file with the correct size, but the content of the file is wrong.

The idea is to receive at the same time several files from one or more clients to the same server... but it dosent works ¿any help?
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by fweil.

I am trying to explain what I understand from your code first :

- Enviafile is the client side sending a file
- RecibeFile is the server receiving files from clients

If you are running each in separate executable programs, even if running on a single PC at this time, you have the Cont.l variable used for file names indexation, which is a global inside each running program (client and server).

So names are probably correctly handled, but you should use a FileName variable for code clarity.

Then in the server side procedure, you set a buffer with a length of the next file to be received (allocatememory before receivenetworkdata). I suppose this is a first issue because you don't know the size of the file to be received at that time. Also you declare the allocatememory to a Buffer variable instead of a *Buffer pointer which, if I do not mistake is a bug.

I am not sure to have seen all and just reply you reading your post, not testing the code on my machine, but I hope this will help to start in solving issues going further in the way you want.

Rgrds

Francois Weil
14, rue Douer
F64100 Bayonne
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Pupil.

I see that you try to send, on the client side, to the server on different ports? Do you have a multiport server, or are your server listening to one specific port, from what i've seen when trying out the network capabillities of PB it's only possible for the server to listen to ONE port at a time(anyone, correct me if i'm wrong). You can use the OpenNetworkConnection() command serveral times after oneother(with same IP and port) and you'll get a different ConnectionID each time, that is if you don't close a connection between the calls.

On the server side you have to differentiate the clients by using the NetworkClientID() command, having this information you can see which client connection triggered the NetworkServerEvent() and easily direct the input to the file associated with that particular connectionID.

Well, just some small thoughts on my side..
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by ricardo.
I see that you try to send, on the client side, to the server on different ports? Do you have a multiport server, or are your server listening to one specific port
I open a new port for every file...

from what i've seen when trying out the network capabillities of PB it's only possible for the server to listen to ONE port at a time(anyone, correct me if i'm wrong).
Mmmm... i have been able to open multiple ports, but the serverevent is shared betwen all of course.
You can use the OpenNetworkConnection() command serveral times after oneother(with same IP and port) and you'll get a different ConnectionID each time, that is if you don't close a connection between the calls.
But using the same port did i will get different results that using new ports?
On the server side you have to differentiate the clients by using the NetworkClientID() command, having this information you can see which client connection triggered the NetworkServerEvent() and easily direct the input to the file associated with that particular connectionID.
Since in my example, all the connectio are opened by the same client, the ClientID are the same, no matter if its a new connection in another port. : )
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Pupil.
Mmmm... i have been able to open multiple ports, but the serverevent is shared betwen all of course.
How do you go about it if you want to close one server port?? It's a no-can-do in purebasic at this stage, so probably you're only supposed to run one server on one port in an application (that's my interpretation atleast).
Since in my example, all the connectio are opened by the same client, the ClientID are the same, no matter if its a new connection in another port. : )
It's isn't that easy, one client can open multiple connections at the same time to a server and on the server side each of these connections get a different ID. You can test this with my example below:

Code: Select all

; server
If OpenWindow(0,0,0,200,100, #PB_Window_SystemMenu, "server") = 0
  End
EndIf
If InitNetwork() = 0
  End
EndIf
If CreateGadgetList(WindowID())
  ListViewGadget(0, 5, 10, 190, 80)
Else
  End
EndIf
If CreateNetworkServer(444) = 0
  End
EndIf


Repeat
  wevent.l = WindowEvent()
  sevent.l = NetworkServerEvent()
  If sevent
    Select sevent
      Case 1 ; New client connected
        AddGadgetItem(0, -1, "new ClientID: $"+Hex(NetworkClientID()))
    EndSelect
  Else
    Delay(1)
  EndIf
Until wevent =  #PB_Event_CloseWindow
And here comes the client:

Code: Select all

; client
If OpenWindow(0,0,0,200,100, #PB_Window_SystemMenu, "client") = 0
  End
EndIf
If InitNetwork() = 0
  End
EndIf
If CreateGadgetList(WindowID())
  ListViewGadget(0, 5, 10, 190, 80)
Else
  End
EndIf
AddGadgetItem(0, -1, "new ConnectionID: $"+Hex(OpenNetworkConnection("127.0.0.1", 444)))
AddGadgetItem(0, -1, "new ConnectionID: $"+Hex(OpenNetworkConnection("127.0.0.1", 444)))
AddGadgetItem(0, -1, "new ConnectionID: $"+Hex(OpenNetworkConnection("127.0.0.1", 444)))

Repeat
  wevent.l = WaitWindowEvent()
Until wevent =  #PB_Event_CloseWindow
First start the server and then start the client for proper results...
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by ricardo.
How do you go about it if you want to close one server port?? It's a no-can-do in purebasic at this stage, so probably you're only supposed to run one server on one port in an application (that's my interpretation atleast).
If you open different ports as i do in my example, just close the ConnectionID of this port (i think).

I will try your example.

One question:

Under your idea... ¿how could i acomplish multithreading to send/receive files at the same time?
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Pupil.
One question:

Under your idea... ¿how could i acomplish multithreading to send/receive files at the same time?
You create a structure that holds the necessary data, on the server side it can look something like this:

Code: Select all

Structure ConnectionType
  ID.l
  In.b[2048]
  InLength.l
  Busy.w
  FileName.s
EndStructure

Declare ReceiveData(*ptr.ConnectionType)

NewList Clients.ConnectionType()

; some initializations and stuff...

Repeat
  WinEvent.l = WindowEvent()
  NetEvent.l = NetworkServerEvent()
  If NetEvent
    Select NetEvent
      Case 1 ; Client connected
      Case 4 ; Client disconnected
        ClientID.l = NetworkClientID()
        ResetList(Clients())
        While NextElement(Clients())
          If Clients()\ID = ClientID
            DeleteElement(Clients())
          EndIf
        Wend
      Default ; data has been received
        ClientID = NetworkClientID()
        *ptr.ConnectionType = 0
        ResetList(Clients())
        While NextElement(Clients())
          If Clients()\ID  = ClientID
            *ptr = Clients()
          EndIf
        Wend
        If *ptr = 0
          If AddElement(Clients())
            *ptr = Clients()
            *ptr\Busy = #FALSE
            *ptr\ID = ClientID
            CreateThread(@ReceiveData(), *ptr)
          EndIf
        Else
          If *ptr\Busy = 0
            CreateThread(@ReceiveData(), *ptr)
          EndIf
        EndIf
    EndSelect
  Else
    Delay(1)
  EndIf
Until WinEvent = #PB_Event_CloseWindow

End

Procedure ReceiveData(*ptr.ConnectionType)
  *ptr\Busy = #TRUE
  *ptr\InLength = ReceiveNetworkData(*ptr\ID, @*ptr\In[0], 2048)
  If *ptr\FileName  ""
  Else
    ; Here you want To either invent a filename or
    ; you might have sent a name with the first packet that
    ; is sent and from that derive a filename...
    ; We'll do this for now:
    *ptr\FileName = "Receivedfile"+Str(*ptr\ID)+".dat"
  EndIf
  If OpenFile(*ptr\ID, *ptr\FileName)
    FileSeek(Lof())
    WriteData(@*ptr\In[0], *ptr\InLength)
    CloseFile(*ptr\ID)
  EndIf
  *ptr\Busy = #FALSE
EndProcedure
I haven't tested it, but hopefully you'll be able to see my line of thought...
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by ricardo.
I haven't tested it, but hopefully you'll be able to see my line of thought...
Hi, Pupil :)

Yes, i see the lines of thoughts and then found some way to do it as i needed.

Really Thanks to all !!
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Pupil.
Hi, Pupil :)

Yes, i see the lines of thoughts and then found some way to do it as i needed.

Really Thanks to all !!
Glad i was able to help. I'll have some waction afk so i won't be able to help anyone for a week or so, perhaps you app is ready when i come back :wink:
Post Reply