custom socket set OnError event

This is the forum for miscellaneous technical/programming questions.

Moderator: 2ffat

rlebeau
BCBJ Author
BCBJ Author
Posts: 1715
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA
Contact:

Re: custom socket set OnError event

Post by rlebeau »

mark_c wrote:why the onError event is never activated and instead the onLookup event is activated?
The OnLookup event is always fired, immediately after the underlying socket is created, and before the OnConnecting event is fired.

The OnError event is not used by the TClientSocket::Open() method in ctBlocking mode. If an error happens on a blocking lookup/connect, an ESocketError exception is thrown instead (unless you call Scktcomp::SetErrorProc() beforehand to assign an error callback procedure). You are not catching that exception in your thread's Execute(), so your thread will terminate itself immediately if a lookup/connect error occurs.

The only methods that fire the OnError event in ctBlocking mode are TCustomWinSocket::SendStream(), TCustomWinSocket::SendBuf(), and TCustomWinSocket::ReceiveBuf() methods, but only if the error code is not WSAEWOULDBLOCK (which it never will be in ctBlocking mode), in which case OnError is fired, and if the ErrorCode is not reset to 0 then an ESocketError exception is thrown.

You are not calling any of those methods in your code, which is why you are not seeing the OnError event being fired in ctBlocking mode.
Last edited by rlebeau on Fri Mar 13, 2020 11:46 am, edited 1 time in total.
Remy Lebeau (TeamB)
Lebeau Software
mark_c
BCBJ Master
BCBJ Master
Posts: 244
Joined: Thu Jun 21, 2012 1:13 am

Re: custom socket set OnError event

Post by mark_c »

I noticed that only error 10054 triggers the OnError event
rlebeau
BCBJ Author
BCBJ Author
Posts: 1715
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA
Contact:

Re: custom socket set OnError event

Post by rlebeau »

mark_c wrote:I noticed that only error 10054 triggers the OnError event
That would fall under "only if the error code is not WSAEWOULDBLOCK" (10035). 10054 is WSAECONNRESET.
Remy Lebeau (TeamB)
Lebeau Software
mark_c
BCBJ Master
BCBJ Master
Posts: 244
Joined: Thu Jun 21, 2012 1:13 am

Re: custom socket set OnError event

Post by mark_c »

how are persistent connections managed through blocking sockets?
For example, with this 1.1.107.47 there is a persistent connection and the socket is no longer unlocked and consequently the associated thread.
rlebeau
BCBJ Author
BCBJ Author
Posts: 1715
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA
Contact:

Re: custom socket set OnError event

Post by rlebeau »

mark_c wrote:how are persistent connections managed through blocking sockets?
For example, with this 1.1.107.47 there is a persistent connection and the socket is no longer unlocked and consequently the associated thread.
I don't understand what you are asking. Please clarify.
Remy Lebeau (TeamB)
Lebeau Software
mark_c
BCBJ Master
BCBJ Master
Posts: 244
Joined: Thu Jun 21, 2012 1:13 am

Re: custom socket set OnError event

Post by mark_c »

sorry, I wrote quickly and without thinking too much.

I was saying that some connections:

1) after the connection has been made,
2) after correctly sending the command "GET / HTTP/1.1\r\nHost: " + myadr + "\r\nConnection: close\r\n\r\n";

they always remain active.

I thought it was a behavior of the HTTP /1.1 protocol however, this does not happen with all connections but only with some and I don't understand why.

So since I open connections using many threads, some never end and always remain active.

If you try to connect with your browser to the address I have given you and check the status of the connection with the netstat command, you will see that the connection always remains ESTABLISHED, even when you close the tab (thread).
So, to close the connection, I am forced to end the whole process.

For example, these threads never end:

C:\temp>netstat -an|find "1."|find ":80"|find "EST"
TCP 192.168.2.4:49600 1.7.136.201:80 ESTABLISHED
TCP 192.168.2.4:50782 1.11.2.5:80 ESTABLISHED
TCP 192.168.2.4:50980 1.9.8.54:80 ESTABLISHED
TCP 192.168.2.4:51320 1.10.133.99:80 ESTABLISHED
TCP 192.168.2.4:51351 1.10.133.130:80 ESTABLISHED
TCP 192.168.2.4:51398 1.10.133.177:80 ESTABLISHED
TCP 192.168.2.4:51447 1.11.194.113:80 ESTABLISHED
TCP 192.168.2.4:52130 1.11.197.2:80 ESTABLISHED
TCP 192.168.2.4:52131 1.11.197.3:80 ESTABLISHED
TCP 192.168.2.4:52132 1.11.197.4:80 ESTABLISHED
TCP 192.168.2.4:52133 1.11.197.5:80 ESTABLISHED
TCP 192.168.2.4:52134 1.11.197.6:80 ESTABLISHED
TCP 192.168.2.4:52135 1.11.197.7:80 ESTABLISHED
TCP 192.168.2.4:52136 1.11.197.8:80 ESTABLISHED
TCP 192.168.2.4:52137 1.11.197.9:80 ESTABLISHED
TCP 192.168.2.4:52426 1.9.13.195:80 ESTABLISHED
TCP 192.168.2.4:52801 1.9.141.131:80 ESTABLISHED
TCP 192.168.2.4:52971 1.9.205.166:80 ESTABLISHED
TCP 192.168.2.4:53370 1.9.207.50:80 ESTABLISHED
TCP 192.168.2.4:53436 1.10.141.153:80 ESTABLISHED
TCP 192.168.2.4:53440 1.9.207.115:80 ESTABLISHED
TCP 192.168.2.4:53564 1.9.207.236:80 ESTABLISHED
TCP 192.168.2.4:53842 1.10.143.45:80 ESTABLISHED
TCP 192.168.2.4:54666 1.9.22.71:80 ESTABLISHED
TCP 192.168.2.4:55041 1.9.150.58:80 ESTABLISHED
TCP 192.168.2.4:55315 1.10.148.234:80 ESTABLISHED
TCP 192.168.2.4:55863 1.10.151.14:80 ESTABLISHED
TCP 192.168.2.4:56878 1.9.220.209:80 ESTABLISHED
TCP 192.168.2.4:57124 1.9.158.90:80 ESTABLISHED
TCP 192.168.2.4:57438 1.9.159.148:80 ESTABLISHED
TCP 192.168.2.4:57493 1.6.232.109:80 ESTABLISHED
TCP 192.168.2.4:58866 1.11.96.217:80 ESTABLISHED
TCP 192.168.2.4:62177 1.6.250.177:80 ESTABLISHED
TCP 192.168.2.4:63106 1.9.181.109:80 ESTABLISHED
TCP 192.168.2.4:63266 1.9.54.223:80 ESTABLISHED
TCP 192.168.2.4:64052 1.6.194.35:80 ESTABLISHED
TCP 192.168.2.4:64081 1.9.121.166:80 ESTABLISHED
TCP 192.168.2.4:64309 1.9.186.24:80 ESTABLISHED
TCP 192.168.2.4:64897 1.9.124.212:80 ESTABLISHED
TCP 192.168.2.4:65395 1.9.63.22:80 ESTABLISHED
rlebeau
BCBJ Author
BCBJ Author
Posts: 1715
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA
Contact:

Re: custom socket set OnError event

Post by rlebeau »

mark_c wrote:I was saying that some connections:

1) after the connection has been made,
2) after correctly sending the command "GET / HTTP/1.1\r\nHost: " + myadr + "\r\nConnection: close\r\n\r\n";

they always remain active.
Not with the example above, it won't. The "Connection: close" request header explicitly instructs the server to CLOSE THE CONNECTION after it sends the response. The client is then REQUIRED to close its socket after receiving the response.
mark_c wrote:I thought it was a behavior of the HTTP /1.1 protocol
What you are referring to is know as an HTTP Keep-Alive, and yes, leaving the connection active is the DEFAULT behavior in HTTP 1.1, but the "Connection: close" header overrides that default. If you want the default behavior, simply omit the "Connection" header altogether:

Code: Select all

"GET / HTTP/1.1\r\nHost: " + myadr + "\r\n\r\n"
Or else set it to "keep-alive" instead (which is required in order to use keep-alives in HTTP 1.0, in case you are communicating with an old server that doesn't understand HTTP 1.1):

Code: Select all

"GET / HTTP/1.1\r\nHost: " + myadr + "\r\nConnection: keep-alive\r\n\r\n"
Either way, the response will tell you what to do next.

If the response is HTTP 1.1+ and a "Connection: close" header is NOT present, or if the response is HTTP 1.0 and a "Connection: keep-alive" header IS present, then the connection is persistent, the server is leaving its end of the connection active indicating that client may do the same if it chooses to. Otherwise, the connection is not persistent and the client MUST close its socket.

Read RFC 2616 Section 8: Connections and RFC 7230 Section 6: Connection Management for more details.
mark_c wrote:however, this does not happen with all connections but only with some and I don't understand why.
Because you are explicitly asking the server to NOT utilize HTTP keep-alives.
mark_c wrote:So since I open connections using many threads, some never end and always remain active.
Then you are not managing them correctly. You MUST pay attention to the response's "Connection" header and act accordingly.
mark_c wrote:If you try to connect with your browser to the address I have given you and check the status of the connection with the netstat command, you will see that the connection always remains ESTABLISHED, even when you close the tab (thread).
Web browsers always use HTTP keep-alives by default, and most HTTP servers honor keep-alive requests. And web browsers are likely to cache and pool keep-alive connections in case they will be reused in the near future. This makes sense in a web browser scenario, since web pages almost always have multiple resources attached to them (images, multimedia, CSS, etc) that need to be requested individually in order to display the whole page, so keep-alives are useful and desirable for that situation. That is primarily why HTTP keep-alives were invented in the first place.

When I use a web browser (FireFox) to access 1.1.107.47, I see the following requests:
GET / HTTP/1.1
Host: 1.1.107.47
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:74.0) Gecko/20100101 Firefox/74.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Pragma: no-cache
Cache-Control: no-cache

HTTP/1.1 200 OK
Date: Wed, 18 Mar 2020 17:17:43 GMT
Content-Type: text/plain; charset=UTF-8
Content-Length: 69
Connection: Keep-Alive
Keep-Alive: timeout=1800, max=0
GET /favicon.ico HTTP/1.1
Host: 1.1.107.47
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:74.0) Gecko/20100101 Firefox/74.0
Accept: image/webp,*/*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache

HTTP/1.1 400 Bad Request
Content-Type: text/plain; charset=UTF-8
Content-Length: 13
Connection: close
The 1st request establishes a persistent keep-alive connection, which gets reused for the 2nd request, which is no longer persistent and gets closed.
mark_c wrote:So, to close the connection, I am forced to end the whole process.
It is not your job to manage a web browser connections. But in your own app, it certainly is.
Last edited by rlebeau on Wed Mar 18, 2020 11:52 am, edited 3 times in total.
Remy Lebeau (TeamB)
Lebeau Software
mark_c
BCBJ Master
BCBJ Master
Posts: 244
Joined: Thu Jun 21, 2012 1:13 am

Re: custom socket set OnError event

Post by mark_c »

Then you are not managing them correctly. You MUST pay attention to the response's "Connection" header and act accordingly.
thanks Remy,
what you mentioned is my problem. Instead, I thought everything happened automatically, but it is not so.
Post Reply