Recent

Author Topic: What is the proper way to wrap a tcp client into a thread?  (Read 1221 times)

Gustavo 'Gus' Carreno

  • Hero Member
  • *****
  • Posts: 1112
  • Professional amateur ;-P
What is the proper way to wrap a tcp client into a thread?
« on: April 16, 2021, 02:34:05 pm »
Hey all,

Hypothetical here...

Let's say that I have a TCP Client component that has events for the usual: OnConnect, OnReceive, etc...

Since I don't want that component to run on the Main thread, I want to nest it, cosily, in a thread.

But this now leaves me with a nagging question: What should the thread's Execute be doing?

I'm guessing that it should see if there is anything in the incoming buffer and read it, otherwise it should sleep for predefined amount of time, right?
And to display this incoming data, use the well know Synchronize.
But what about that event OnReceive, where should I connect that? Or should I not connect it?

I'm also guessing that if I want the GUI to send data through the TCP Client I need to have the access to the TCP Client inside a thread safe manner, with a Critical Section.

Is this the proper way to do it?
And is there a simple example I can look at to learn the details that I've glossed over here?

Cheers,
Gus
Lazarus 3.99(main) FPC 3.3.1(main) Ubuntu 23.10 64b Dark Theme
Lazarus 3.0.0(stable) FPC 3.2.2(stable) Ubuntu 23.10 64b Dark Theme
http://github.com/gcarreno

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: What is the proper way to wrap a tcp client into a thread?
« Reply #1 on: April 16, 2021, 03:13:09 pm »
If you're using threads and only want an unembellished TCP/UDP connection then I don't think there's any advantage to using a prebuilt component. You /particularly/ don't want to use LNet, which predates wide popularity of threads and contains code which is at best tricky... I'd probably grade it "Hard Very Difficult" and quite frankly I've seen lumps of rock I'm happier with :-)

So basically you put whatever you want in your Synchronize or QueueAsyncCall handler, and it wouldn't be too much of a stretch to say that that handler is comparable with what you'd hang on an OnReceive() etc.

I'll give some thought to what I've got in the way of an example but I'm more oriented towards UDP than TCP.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Gustavo 'Gus' Carreno

  • Hero Member
  • *****
  • Posts: 1112
  • Professional amateur ;-P
Re: What is the proper way to wrap a tcp client into a thread?
« Reply #2 on: April 16, 2021, 03:32:56 pm »
Hey Mark,

I'll give some thought to what I've got in the way of an example but I'm more oriented towards UDP than TCP.

Many thanks for giving it a go!!

Let me leave you with a better practical case, maybe that will help.

Let's say that I'm implementing a GUI cryptocoin miner.
The TCP client connects, and stays connected, to the pool server and is given work, or pings via the downstream.
In the meantime, a thread pool the size of CPU cores/threads is doing the work-munching and then needs to report back via the TCP Client's upstream on the other thread.

How would this kinda thing be implemented?

I have the gist of the thing in my mind. I'm just troubled on where I should put the Critical sections, I think...
As per my default, I started thinking about this while I was already in bed and it got to the point where I got up again and came here.
I can flesh out my mind vision but it'll have to be after some ZzZzZz's cuz I'm all out of steam right now :)

Cheers,
Gus
Lazarus 3.99(main) FPC 3.3.1(main) Ubuntu 23.10 64b Dark Theme
Lazarus 3.0.0(stable) FPC 3.2.2(stable) Ubuntu 23.10 64b Dark Theme
http://github.com/gcarreno

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: What is the proper way to wrap a tcp client into a thread?
« Reply #3 on: April 16, 2021, 03:57:33 pm »
First, consider that the server pool to which you're connecting might break your connection when it load-balances, in the same way that a pool of SQL servers might.

I think the sort of thing you're saying is that you have a thread reading your incoming network traffic and (in the case of TCP) assembling messages, and then passing the job to another background thread. In that case you don't use Synchronize() or QueueAsyncCall() since those are strictly for passing work to the main/foreground/GUI thread; instead you have a brief critical section which enqueues the job for the least-busy thread and then if necessary kicks it to stop it waiting.

I've not really got an example that you'd enjoy reading... try https://www.freepascal.org/docs-html/current/rtl/sockets/accept.html

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Gustavo 'Gus' Carreno

  • Hero Member
  • *****
  • Posts: 1112
  • Professional amateur ;-P
Re: What is the proper way to wrap a tcp client into a thread?
« Reply #4 on: April 16, 2021, 04:24:02 pm »
Hey Mark,

First, consider that the server pool to which you're connecting might break your connection when it load-balances, in the same way that a pool of SQL servers might.

Yeap, gotcha. I'm aware of this, but I haven't got there yet. Remember: first get it to work, then get it right :)

I think the sort of thing you're saying is that you have a thread reading your incoming network traffic and (in the case of TCP) assembling messages, and then passing the job to another background thread. In that case you don't use Synchronize() or QueueAsyncCall() since those are strictly for passing work to the main/foreground/GUI thread; instead you have a brief critical section which enqueues the job for the least-busy thread and then if necessary kicks it to stop it waiting.

Yes, this is what I have in mind for the Server->Client->WorkThread.
What I'm a bit at a loss is the WorkThread->Client->Server for job completion report... Mainly because the socket maybe blocking due to lack of data and I don't know if a critsec will do.

I've not really got an example that you'd enjoy reading... try https://www.freepascal.org/docs-html/current/rtl/sockets/accept.html

That link as an example of a server, not a client :P

But as usual, many thanks for the answers so far!!!

Cheers,
Gus
Lazarus 3.99(main) FPC 3.3.1(main) Ubuntu 23.10 64b Dark Theme
Lazarus 3.0.0(stable) FPC 3.2.2(stable) Ubuntu 23.10 64b Dark Theme
http://github.com/gcarreno

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: What is the proper way to wrap a tcp client into a thread?
« Reply #5 on: April 16, 2021, 04:39:46 pm »
I think you need to stop and consider whether you want TCP (stream-based, reliable) or UDP (message-based, unreliable), or even SCTP (message based, reliable BUT unsupported by most 4G etc. connections).

You need to go through much the same sequence of address generation etc. for both client and server. There's an "option" to set a socket non-blocking, and you can obviously use fpSelect().

MarkMLl


MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Gustavo 'Gus' Carreno

  • Hero Member
  • *****
  • Posts: 1112
  • Professional amateur ;-P
Re: What is the proper way to wrap a tcp client into a thread?
« Reply #6 on: April 16, 2021, 06:34:18 pm »
Hey Mark,

I think you need to stop and consider whether you want TCP (stream-based, reliable) or UDP (message-based, unreliable), or even SCTP (message based, reliable BUT unsupported by most 4G etc. connections).

You need to go through much the same sequence of address generation etc. for both client and server. There's an "option" to set a socket non-blocking, and you can obviously use fpSelect().

Those are all good and valid suggestions, but alas, I can only abide by the protocol that the server has and that server is out of my hands.

My attempt is to make a NosoCoin miner and I don't control the Pool Server side of the code :)

Cheers,
Gus
Lazarus 3.99(main) FPC 3.3.1(main) Ubuntu 23.10 64b Dark Theme
Lazarus 3.0.0(stable) FPC 3.2.2(stable) Ubuntu 23.10 64b Dark Theme
http://github.com/gcarreno

 

TinyPortal © 2005-2018