Having problems with your account or logging in?
A lot of changes are happening in the community right now. Some may affect you. READ MORE HERE
cobsolv_global_co_za Absent Member.
Absent Member.
718 views

C$SOCKET

Jump to solution

When I use AGS-CREATE-CLIENT, it takes an eternity to time out if it cannot make a connection (by which time users have broken-out). Is there any way to control this? (The manual states that "The length of time is dependent on the underlying socket layer".)

1 Solution

Accepted Solutions
Highlighted
Micro Focus Expert
Micro Focus Expert

RE: C$SOCKET

Jump to solution

My knowledge of C$SOCKET is very limited, but I know a few things about TCP. Let me start with some background.

I don't know how AGS-CREATE-CLIENT is implemented, but if it's just doing a straightforward blocking connect call, then the timeout depends on many factors:

  • If it can't make a connection because there is no process listening on the remote port, but the peer system is available, then it will time out as soon as an IP round trip can occur. The client will send a TCP SYN, and receive a TCP RST from the peer.
  • If the peer is available and there is a process listening on the remote port, but the listen queue is full (because the peer process hasn't had enough time to accept all the inbound conversation requests), then one of two things might happen:
    • Some broken TCP/IP stacks, notably Windows, will send a RST, just as if there were no listening process.
      • Some client implementations, knowing Windows is broken this way, retry if they get an RST. In this case the actual application-visible timeout will be the time taken for this TCP round-trip times the number of retries.
    • A properly-designed stack will simply throw away connection attempts that can't fit in the listen queue. The client will time out and retry, as discussed below. The total timeout in this case will be long.
  • If the peer is unavailable, various things can happen:
    • There may be no route to the peer. At some stage, some system along the path to the peer's IP address should respond with an ICMP HOST_UNREACHABLE or NET_UNREACHABLE error.
      • This could potentially take a while to be generated and get back to the client, depending on the path topology and link speed. Usually it would be on the order of seconds, however.
      • However, some routers and end nodes are configured to discard ICMP errors, in which case the client gets nothing back, times out, and retries.
    • There may be a route to the peer but the peer is non-responsive (not running, hung, etc). Nothing comes back to the client, it times out and retries.
  • The peer is available and there's room in the listen queue, but the peer process isn't responding. In this case the client connects but the peer never responds further. I'm guessing that in this case AGS-CREATE-CLIENT would return when the connection is made, however.

In the case of a black hole - any of the cases where the client doesn't see any response to its SYN - TCP will time out and retry. The timeout and number of retries in question are determined by the stack ("underlying socket layer"). The timer used is the TCP Retransmit timer or RTO. RTO is a varying timer; it starts off small but increases exponentially each time TCP retransmits, until it gets a response. RTO was originally defined in RFC 793, then updated by RFC 1122, and finally by RFC 6298.

The modern RTO algorithm starts at a small value, at least 1 second, and doubles each time TCP has to retransmit a given packet. So when trying to connect to a black-hole destination, you might have a sequence like this:

  1. Client sends SYN, waits 1 second (initial RTO value).
  2. Client resends SYN, waits 2 seconds (new RTO value, twice the old one).
  3. Client resends SYN, waits 4 seconds.
  4. Client resends SYN, waits 8 seconds.
  5. ... and so on, until the client's stack gives up.

The upper bound on the RTO given by RFC 1122 is 240 seconds, or four minutes. By the time we reach it, we've waited a total of 255 seconds (the sum of the powers of 2 less than 240), in 8 attempts to connect.

If, say, your stack is configured to try 10 times to connect, and uses the standard RFC 1122 values, a black-hole destination will leave the client hanging for 255 + 2*240 = 735 seconds, or 12 minutes 15 seconds.

Consequently, many TCP clients either give the user the opportunity to abort the connection early, or do so automatically. They may do that with a second thread, or by using a non-blocking connect and polling/multiplexing for success, or by using some separate interruption mechanism like the UNIX alarm system call (which raises SIGALRM).

It's tough to do any of those in a traditional procedural library such as C$SOCKET without breaking things in some calling applications. Some apps may be single-threaded. Many won't tolerate a library messing about with asynchronous operations. And using a non-blocking connect would either require another thread or require the application to keep calling back into the library.

Now, some modern socket libraries let the application set a connection timeout on the socket before trying to connect. I don't know if C$SOCKET exposes that, assuming it's supported on the platform you're using.

And many stacks let you configure retransmission timeout parameters and connection timeouts - but generally only on a system-wide basis, which could be problematic.

In short (ha!), my guess is that no, there's no way to control this - at least not any straightforward way. But someone who knows more about C$SOCKET may correct me on that.

One possible workaround is to move socket operations into a separate thread, or even a separate process, so they're not blocking the UI.

0 Likes
5 Replies
Highlighted
Micro Focus Expert
Micro Focus Expert

RE: C$SOCKET

Jump to solution

My knowledge of C$SOCKET is very limited, but I know a few things about TCP. Let me start with some background.

I don't know how AGS-CREATE-CLIENT is implemented, but if it's just doing a straightforward blocking connect call, then the timeout depends on many factors:

  • If it can't make a connection because there is no process listening on the remote port, but the peer system is available, then it will time out as soon as an IP round trip can occur. The client will send a TCP SYN, and receive a TCP RST from the peer.
  • If the peer is available and there is a process listening on the remote port, but the listen queue is full (because the peer process hasn't had enough time to accept all the inbound conversation requests), then one of two things might happen:
    • Some broken TCP/IP stacks, notably Windows, will send a RST, just as if there were no listening process.
      • Some client implementations, knowing Windows is broken this way, retry if they get an RST. In this case the actual application-visible timeout will be the time taken for this TCP round-trip times the number of retries.
    • A properly-designed stack will simply throw away connection attempts that can't fit in the listen queue. The client will time out and retry, as discussed below. The total timeout in this case will be long.
  • If the peer is unavailable, various things can happen:
    • There may be no route to the peer. At some stage, some system along the path to the peer's IP address should respond with an ICMP HOST_UNREACHABLE or NET_UNREACHABLE error.
      • This could potentially take a while to be generated and get back to the client, depending on the path topology and link speed. Usually it would be on the order of seconds, however.
      • However, some routers and end nodes are configured to discard ICMP errors, in which case the client gets nothing back, times out, and retries.
    • There may be a route to the peer but the peer is non-responsive (not running, hung, etc). Nothing comes back to the client, it times out and retries.
  • The peer is available and there's room in the listen queue, but the peer process isn't responding. In this case the client connects but the peer never responds further. I'm guessing that in this case AGS-CREATE-CLIENT would return when the connection is made, however.

In the case of a black hole - any of the cases where the client doesn't see any response to its SYN - TCP will time out and retry. The timeout and number of retries in question are determined by the stack ("underlying socket layer"). The timer used is the TCP Retransmit timer or RTO. RTO is a varying timer; it starts off small but increases exponentially each time TCP retransmits, until it gets a response. RTO was originally defined in RFC 793, then updated by RFC 1122, and finally by RFC 6298.

The modern RTO algorithm starts at a small value, at least 1 second, and doubles each time TCP has to retransmit a given packet. So when trying to connect to a black-hole destination, you might have a sequence like this:

  1. Client sends SYN, waits 1 second (initial RTO value).
  2. Client resends SYN, waits 2 seconds (new RTO value, twice the old one).
  3. Client resends SYN, waits 4 seconds.
  4. Client resends SYN, waits 8 seconds.
  5. ... and so on, until the client's stack gives up.

The upper bound on the RTO given by RFC 1122 is 240 seconds, or four minutes. By the time we reach it, we've waited a total of 255 seconds (the sum of the powers of 2 less than 240), in 8 attempts to connect.

If, say, your stack is configured to try 10 times to connect, and uses the standard RFC 1122 values, a black-hole destination will leave the client hanging for 255 + 2*240 = 735 seconds, or 12 minutes 15 seconds.

Consequently, many TCP clients either give the user the opportunity to abort the connection early, or do so automatically. They may do that with a second thread, or by using a non-blocking connect and polling/multiplexing for success, or by using some separate interruption mechanism like the UNIX alarm system call (which raises SIGALRM).

It's tough to do any of those in a traditional procedural library such as C$SOCKET without breaking things in some calling applications. Some apps may be single-threaded. Many won't tolerate a library messing about with asynchronous operations. And using a non-blocking connect would either require another thread or require the application to keep calling back into the library.

Now, some modern socket libraries let the application set a connection timeout on the socket before trying to connect. I don't know if C$SOCKET exposes that, assuming it's supported on the platform you're using.

And many stacks let you configure retransmission timeout parameters and connection timeouts - but generally only on a system-wide basis, which could be problematic.

In short (ha!), my guess is that no, there's no way to control this - at least not any straightforward way. But someone who knows more about C$SOCKET may correct me on that.

One possible workaround is to move socket operations into a separate thread, or even a separate process, so they're not blocking the UI.

0 Likes
PiGi78 Absent Member.
Absent Member.

RE: C$SOCKET

Jump to solution
Hi.

I used the C$SOCKET few times and I see that the connection works in a strange way:
- If the server is up but no process is listening on the requested port, the runtime needs about 1 minutes to raise the timeout
- If the server is not running (no machine with that ID), then the call returns istantaneously to the caller


I don't know why, but this is how C$SOCKET worked in my scenario
0 Likes
Micro Focus Expert
Micro Focus Expert

RE: C$SOCKET

Jump to solution
You would need to look at a wire trace to see exactly what's happening, but it's likely that when the server is not running, you get an ICMP HOST_UNREACHABLE or possibly NET_UNREACHABLE response from a router, or from a switch if the target host is on the same network segment (as determined by your routing tables).

In this case, the application code is informed quickly that there is no such destination, and there probably won't be one soon, because the target IP address isn't in use.

When there is a system at the destination address but no listening socket on the port, though, the remote machine should send a TCP RST response. In that case the local stack should return ECONNREFUSED, but many libraries and applications retry that for a while, because Windows (and possibly some other implementations) incorrectly sends an RST in other situations as well, in particular when the listen queue is full.
0 Likes
samueleverton Absent Member.
Absent Member.

RE: C$SOCKET

Jump to solution

The point is that the completed connection will have a unique 4-tuple of (client IP address, client port, server IP address, server port).

When it comes to the processing, there are various ways of dealing with it. You can use an iterative server which deals with one request before dealing with any others. Or you can create a concurrent server in either of two different ways. One way is with a threaded server where a thread (from a pool, or newly created for each incoming connection) deals with the new request while the main thread goes back to accept new incoming requests. The alternative is that you create a forking server where the main server process forks and the child process deals with the new connection while the parent process closes the connection and goes back to listening for the next connection request.

More info: https://www.routerinstructions.com/https://www.routerinstructions.com/

0 Likes
Micro Focus Expert
Micro Focus Expert

RE: C$SOCKET

Jump to solution
I'm not sure how this applies to the OP's question, which was about the client (active-open) side, not the server (passive-open) one. Most clients only manage one conversation at a time, and I don't see anything in the original post to suggest otherwise.

Besides the multithreaded and forking architectures, an application that has to handle multiple conversations can use multiplexing (generally with asynchronous I/O, though some applications may tolerate blocking I/O operations with a multiplexed design). Multiplexing is often more efficient than multithreading or forking. Historically interrupt-driven and co-routine architectures were also used by communications-bound applications, but the BSD sockets API and its descendants, and the POSIX process model, aren't a good fit for those approaches.
0 Likes
The opinions expressed above are the personal opinions of the authors, not of Micro Focus. By using this site, you accept the Terms of Use and Rules of Participation. Certain versions of content ("Material") accessible here may contain branding from Hewlett-Packard Company (now HP Inc.) and Hewlett Packard Enterprise Company. As of September 1, 2017, the Material is now offered by Micro Focus, a separately owned and operated company. Any reference to the HP and Hewlett Packard Enterprise/HPE marks is historical in nature, and the HP and Hewlett Packard Enterprise/HPE marks are the property of their respective owners.