1. Eunet or EuLibnet or TCP socket library (or socket.e)

I have to write a custom invoice maker for our company. (They realized that the client-facing Excel or Word documents later handed to Finance to key into the accounting system were not a good idea). Anyway, I want to utilise a multi-client server system. My question is: Which communications library would suit my purposes best?

The Server will manage a small database of transactions. The Client will need to read various data items from the Server and send confirmed transactions to the Server. The size of the data strings sent to the Server will vary from eg 30 to 2000 bytes. The Server could return data between, say, 20 bytes to 20 Kbytes. Number of users could vary from 1 to 10. The basic requirements are:

  • Simplicity
  • Performance
  • Robustness

Another factor to consider is Synchronous vs Asynchronous transmissions. Personally I would favour Synchronous since the Client code should be simpler. However, a problem with the Server could stop the Client dead in its tracks. So I'm just a bit cautious about committing to it.

Has someone had experience with this sort of project that could advise? TIA.

EDIT: I'm thinking that the Server could simply be a console app that can respond quickly to requests but the Client will always be a Windows GUI program.

EDIT2: Actually, a synchronous call with a timeout would solve the blocking issue. Looks like others have had the same issue. This solution uses UDP.

Spock

new topic     » topic index » view message » categorize

2. Re: Eunet or EuLibnet or TCP socket library (or socket.e)

Spock said...

I have to write a custom invoice maker for our company. (They realized that the client-facing Excel or Word documents later handed to Finance to key into the accounting system were not a good idea). Anyway, I want to utilise a multi-client server system. My question is: Which communications library would suit my purposes best?

I would recommend ZeroMQ as the "best" solution for this type of communication. However, the current wrapper in The Archive is for version 2.0 (version 3.x and 4.x are much better) and it is incomplete and does not work correctly on Windows without some modification (needs '+' added to the define_c_func calls for CDECL). Ultimately, somebody needs to wrap the CZMQ API for Euphoria, but I've had trouble getting things build correctly on my system to even get started with that. But that's neither here nor there I guess.

Spock said...

The Server will manage a small database of transactions. The Client will need to read various data items from the Server and send confirmed transactions to the Server. The size of the data strings sent to the Server will vary from eg 30 to 2000 bytes. The Server could return data between, say, 20 bytes to 20 Kbytes. Number of users could vary from 1 to 10. The basic requirements are:

  • Simplicity
  • Performance
  • Robustness

You can accomplish this via Core Sockets. I like to combine this with Serialization to send/receive Euphoria objects on the wire. I've created a demo for you here: Socket object demo.

Spock said...

Another factor to consider is Synchronous vs Asynchronous transmissions. Personally I would favour Synchronous since the Client code should be simpler. However, a problem with the Server could stop the Client dead in its tracks. So I'm just a bit cautious about committing to it.

With the data sizes you're talking about, a synchronous server shouldn't cause any perceivable delays. You can read/write megabytes of data on the database in a fraction of a second. My biggest concern is that Euphoria is not very resilient when it comes to crashes or errors. If something causes a hard error (an invalid data type, for instance) then the server would crash and you'd have to restart it. Now, there are ways to get around that, but when the server exits, your existing TCP sockets would be dropped and need to be reconnected, and your client application would have to somehow negotiate that.

You could accomplish a pseudo-asynchronous server by combining the select function with Multi-tasking where you have one task to listen for incoming connections, that would then pass of those connections to a separate sub-task that talks to the client. Using select allows you determine if a socket has data waiting and, if not, continue on to other tasks. I could mock up a demo for you if you'd like.

Spock said...

EDIT: I'm thinking that the Server could simply be a console app that can respond quickly to requests but the Client will always be a Windows GUI program.

That would be the correct approach to take. You could also even implement the console app as an actual service. There is a Windows Services Library in The Archive that might be of some help here.

Spock said...

EDIT2: Actually, a synchronous call with a timeout would solve the blocking issue. Looks like others have had the same issue.

I wouldn't be worried about people having issues in the browser with AJAX calls. That's completely different from how core sockets are implemented in Euphoria. The JavaScript engines used in web browsers (and Node.js) are designed to be natively asynchronous. Euphoria is not. You will not have the same problems they are having.

Spock said...

This solution uses UDP.

Wow. Nope. DO NOT use UDP for this. UDP is inherently unreliable. You could lose packets on the wire and you would never know. It's not something that's appropriate for this type of communication. Even if you did write some additional code to determine when packets were lost and request re-transmission from the other end, all you're doing is reinventing the wheel when all of these problems are corrected by TCP. Just use TCP.


Spock said...

Has someone had experience with this sort of project that could advise? TIA.

I have quite a lot of experience with this. My best advice would be to avoid writing your own data server and also avoid writing your own TCP data protocol. These types of low-level "inventions" are prone to human error and can lead to lots and lots of feature bloat or spaghetti code over time. What's most concerning, is that this needs to be a production system for several people, but you'd effectively be developing it in the field. You can only ever do so much development testing, and as soon as you have your first server crash in production, you'd have to develop and implement a fix to keep that from happening again, in real time.

My ultimate recommendation would be to use a MySQL or Postgres server and Jeremy's EDBI library to connect your clients to it. This solves all of your server-related problems and you won't have to write a single bit of server code. No protocols to invent, no worries about synchronicity, no server-side error recovery problems, none of that. Just design your client to connect to the database and manage the shared data from there.

-Greg

new topic     » goto parent     » topic index » view message » categorize

3. Re: Eunet or EuLibnet or TCP socket library (or socket.e)

Hi Greg, Thanks for the very informative response. It has helped clarify my thinking on the matter.

ghaberek said...
Spock said...

I have to write a custom invoice maker... a multi-client server system.. Which communications library would suit my purposes best?

The Server will manage a small database of transactions. The Client will need to read various data items from the Server and send confirmed transactions to the Server. The size of the data strings sent to the Server will vary from eg 30 to 2000 bytes. The Server could return data between, say, 20 bytes to 20 Kbytes. Number of users could vary from 1 to 10. The basic requirements are:

  • Simplicity
  • Performance
  • Robustness

You can accomplish this via Core Sockets. I like to combine this with Serialization to send/receive Euphoria objects on the wire. I've created a demo for you here: Socket object demo.

I like the idea of using core sockets since it seems simple enough and I won't have to install any other software and I am obliged to have a better technical understanding. There is just the synchronicity/connectivity issue to solve.

ghaberek said...

With the data sizes you're talking about, a synchronous server shouldn't cause any perceivable delays. You can read/write megabytes of data on the database in a fraction of a second. My biggest concern is that Euphoria is not very resilient when it comes to crashes or errors. If something causes a hard error (an invalid data type, for instance) then the server would crash and you'd have to restart it. Now, there are ways to get around that, but when the server exits, your existing TCP sockets would be dropped and need to be reconnected, and your client application would have to somehow negotiate that.

The client-server communications will be quite sparse (and the user load light). At client initialisation the previous few months transactions (for that user) will be loaded into the client as a single read-only table. When a new transaction is created in the client it gets sent to the server which then confirms the event. That is really the core of the transmissions. So on the client side I think it would work as a synchronous socket call that times out. The dropped TCP connection could be managed by preceding each call with a check that the connection is still up. Can select be used to check connectivity? I presume so since socket.e refers to ERR_NOTCONN indicating that I can test for that condition.

ghaberek said...

You could accomplish a pseudo-asynchronous server by combining the select function with Multi-tasking where you have one task to listen for incoming connections, that would then pass of those connections to a separate sub-task that talks to the client. Using select allows you determine if a socket has data waiting and, if not, continue on to other tasks.

I would prefer to not use tasks, if at all possible. Would some form of polling work instead?

ghaberek said...

My best advice would be to avoid writing your own data server and also avoid writing your own TCP data protocol. These types of low-level "inventions" are prone to human error and can lead to lots and lots of feature bloat or spaghetti code over time. What's most concerning, is that this needs to be a production system for several people, but you'd effectively be developing it in the field. You can only ever do so much development testing, and as soon as you have your first server crash in production, you'd have to develop and implement a fix to keep that from happening again, in real time.

I understand what you're saying.. In my case the main user/beneficiary sits in the desk just opposite me so any crashes during the initial production will be well contained prior to the wider deployment.

Spock

new topic     » goto parent     » topic index » view message » categorize

4. Re: Eunet or EuLibnet or TCP socket library (or socket.e)

Spock said...

The client-server communications will be quite sparse (and the user load light). At client initialisation the previous few months transactions (for that user) will be loaded into the client as a single read-only table. When a new transaction is created in the client it gets sent to the server which then confirms the event. That is really the core of the transmissions. So on the client side I think it would work as a synchronous socket call that times out. The dropped TCP connection could be managed by preceding each call with a check that the connection is still up.

I don't think you need to keep the TCP connections open between the clients and server. This is the process I imagine you'd take:

# Client Server
1 Connect to server
2 Accept connection from client
3 Send request for new transaction ID
4 Receive request for new transaction ID
5 Send new transaction ID to client
6 Receive new transaction ID
7 Send transaction ID and data
8 Receive transaction ID and data
9 Send SUCCESS or FAILED status
10 Close client socket
11 Receive status from server
12 Close local socket

This is how a lot of simple TCP protocols, like HTTP, work: the connection only lives for the duration of the request. More advanced protocols (especially databases) utilize connection pooling, which allows the programmer to design the application as if the connection were always open, but underneath, the connection can idle out, time out, error out, create multiple channels, etc. without the programmer ever knowing. But we don't really have that luxury with core sockets.

Spock said...

Can select be used to check connectivity? I presume so since socket.e refers to ERR_NOTCONN indicating that I can test for that condition.

That's exactly what select() is for: to poll the state of one or more sockets and act accordingly. However, as stated, I would not recommend relying on the TCP connection to remain open. It's a lot easier if your connections have the same lifetime as your transactions.

Spock said...

I would prefer to not use tasks, if at all possible. Would some form of polling work instead?

You certainly don't need to use tasks. I use tasks to provide a stronger separation of concerns in my networking model. That is, there the primary task is listening for new connections and additional tasks (or one task processing a queue) is handling the clients' data in chunks at a time. But since your data sizes are so small, I doubt you'll need to break things down into chunks.

-Greg

new topic     » goto parent     » topic index » view message » categorize

5. Re: Eunet or EuLibnet or TCP socket library (or socket.e)

ghaberek said...
Spock said...

The client-server communications will be quite sparse (and the user load light). At client initialisation the previous few months transactions (for that user) will be loaded into the client as a single read-only table. When a new transaction is created in the client it gets sent to the server which then confirms the event. That is really the core of the transmissions. So on the client side I think it would work as a synchronous socket call that times out. The dropped TCP connection could be managed by preceding each call with a check that the connection is still up.

I don't think you need to keep the TCP connections open between the clients and server. This is the process I imagine you'd take:

# Client Server
1 Connect to server
2 Accept connection from client
3 Send request for new transaction ID
4 Receive request for new transaction ID
5 Send new transaction ID to client
6 Receive new transaction ID
7 Send transaction ID and data
8 Receive transaction ID and data
9 Send SUCCESS or FAILED status
10 Close client socket
11 Receive status from server
12 Close local socket

This is how a lot of simple TCP protocols, like HTTP, work: the connection only lives for the duration of the request..

-Greg

This is even better by making each event independent. In the above table there is a user delay of a few minutes between items 6 & 7. So I could then break the transmission into 2 distinct chunks. And the server loop itself will be much simpler with no past/future to worry about - only the here and now.

Edit - In testing the client/server I discovered there is a buffer limit (in my case 1023 bytes). So files of arbitrary size can't be sent all in one go. Is there a standard solution to this?

Spock

new topic     » goto parent     » topic index » view message » categorize

6. Re: Eunet or EuLibnet or TCP socket library (or socket.e)

I've read the Euphoria source code, it uses a fixed length buffer for the socket IO, of 1024 bytes, and sacrificing the last byte. I had too perceived this 1023 limitation while developing a scgi server.

Seems to me the solution is, first send a "start file trans" packet, containing the size and checksum of the data, then send various "file-chunk" packets, each one carrying a "chunk id", maybe a "file id".

new topic     » goto parent     » topic index » view message » categorize

7. Re: Eunet or EuLibnet or TCP socket library (or socket.e)

acEduardo said...

I've read the Euphoria source code, it uses a fixed length buffer for the socket IO, of 1024 bytes, and sacrificing the last byte. I had too perceived this 1023 limitation while developing a scgi server.

Seems to me the solution is, first send a "start file trans" packet, containing the size and checksum of the data, then send various "file-chunk" packets, each one carrying a "chunk id", maybe a "file id".

I mostly agree with this. This guy has a similar solution but using only the length prefix. I just wish there was a shrink-wrapped solution in Euphoria available for download.

Spock

new topic     » goto parent     » topic index » view message » categorize

8. Re: Eunet or EuLibnet or TCP socket library (or socket.e)

ghaberek said...
Spock said...

I have to write a custom invoice maker for our company. (They realized that the client-facing Excel or Word documents later handed to Finance to key into the accounting system were not a good idea). Anyway, I want to utilise a multi-client server system.

With the data sizes you're talking about, a synchronous server shouldn't cause any perceivable delays. You can read/write megabytes of data on the database in a fraction of a second...

I added message framing and a receive loop to the experimental code. The basic socket code always could send an arbitrary length data. My receive function can now receive arbitrary lengths - Yippee ! You are right about the speed. I tested the throughput (2-way) up to 2,000,000 bytes and it takes only 1/6 second running the server and client on a single computer. Over an actual network the speed will drop but my modest app would be happy with even 5% of that rate.

ghaberek said...

You could accomplish a pseudo-asynchronous server by combining the select function with Multi-tasking ..

I have been reading about Finite State Machines. They seem well suited for solving the problem of parallel but independent actions. Once the single instance server core is stable I'll add an FSM to allow multiple connections in parallel. Muhahaha...

Spock

new topic     » goto parent     » topic index » view message » categorize

9. Re: Eunet or EuLibnet or TCP socket library (or socket.e)

Spock said...
ghaberek said...

You could accomplish a pseudo-asynchronous server by combining the select function with Multi-tasking ..

I have been reading about Finite State Machines. They seem well suited for solving the problem of parallel but independent actions. Once the single instance server core is stable I'll add an FSM to allow multiple connections in parallel. Muhahaha...

Spock

Ok. FSM has been added and seems to be working ok for multiple connections. What I now need is some guidance on timeouts for receiving large files. The basic process is

1. Connect to other machine
2. Receive message prefix indicating total length of the data
3. Receive next block of data
4. repeat 3 until data buffer reaches the length value
5. Close connection

There are several places for timeouts.

i) When the connection is made till the prefix is received
ii) Between each subsequent block of data
iii) The total time to receive all the data (optional?)

Are there any suggestions as to how long the maximum length of each stage chould be? I am also thinking that (barring network delays) the timeouts should be based somewhat on the number of active connections.

Spock

new topic     » goto parent     » topic index » view message » categorize

10. Re: Eunet or EuLibnet or TCP socket library (or socket.e)

Spock said...

Are there any suggestions as to how long the maximum length of each stage chould be? I am also thinking that (barring network delays) the timeouts should be based somewhat on the number of active connections.

Maybe have a look at execute_request() in std/net/http.e to see how it handles timeouts.

-Greg

new topic     » goto parent     » topic index » view message » categorize

11. Re: Eunet or EuLibnet or TCP socket library (or socket.e)

ghaberek said...
Spock said...

Are there any suggestions as to how long the maximum length of each stage chould be? I am also thinking that (barring network delays) the timeouts should be based somewhat on the number of active connections.

Maybe have a look at execute_request() in std/net/http.e to see how it handles timeouts.

-Greg

Thanks for the reference. In that example the default timeout for the HTTP send-receive is 15 seconds but can be altered by the user. Other timeouts I have seen range from, eg, 30 seconds upwards. I'll use those figures as starting estimates and refine the concept over time.

Spock

new topic     » goto parent     » topic index » view message » categorize

12. Re: Eunet or EuLibnet or TCP socket library (or socket.e)

Spock said...
ghaberek said...
Spock said...

Are there any suggestions as to how long the maximum length of each stage chould be? I am also thinking that (barring network delays) the timeouts should be based somewhat on the number of active connections.

Maybe have a look at execute_request() in std/net/http.e to see how it handles timeouts.

-Greg

Thanks for the reference. In that example the default timeout for the HTTP send-receive is 15 seconds but can be altered by the user. Other timeouts I have seen range from, eg, 30 seconds upwards. I'll use those figures as starting estimates and refine the concept over time.

Spock

I'm pleased with the server's performance now. I can firebomb it with dozens of simultaneous connections sending random strings (1k to 100k) of data and it handles them all without dropping any.. except when the string is less than the buffer size (Maximum Transmission Unit) thanks to Nagle's algorithm which coalesces subsequent "sends" until the buffer is full and then actually sends the data out. In my case it just times out the connection. I haven't been able to fix it and not sure where to start. I can sidestep the issue by ensuring that each string of data has a minimum size but that's really just a hack.

Spock
Forked into: Libharu dll trouble

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu