[Rd] Question on non-blocking socket

Tomas Kalibera tom@@@k@||ber@ @end|ng |rom gm@||@com
Wed Feb 15 17:17:24 CET 2023


On 2/15/23 16:44, Ben Engbers wrote:
> Hi
>
> Op 15-02-2023 om 14:38 schreef Tomas Kalibera:
>> On 2/15/23 01:24, Ben Engbers wrote:
>>> Hi,
>>>
>>> December 27, 2021 I started a thread asking for help troubleshooting 
>>> non-blocking sockets.
> ..
>
>>> I have two questions.
>>> The first is where I can find R documentation on proper use of 
>>> non-blocking sockets and on the proper use of the socketSelect 
>>> function?
>>
>> In addition to the demos I sent to you in that 2021 thread on 
>> R-pkg-devel, you could also have a look at how it is used in R 
>> itself, in the parallel package, in snowSOCK.R, to set up the snow 
>> cluster in parallel. Some hints may be also found in the blog post 
>> https://blog.r-project.org/2020/03/17/socket-connections-update/. 
>> But, in principle, R API is just a thin layer on top of what the OS 
>> provides, so general literature and tutorials on sockets should help, 
>> there should be even textbooks used at CS universities in networking 
>> classes.
> Thanks for the suggestions!
>
>> Basically select() can tell you when data is ready (on input), when 
>> the socket interface is able to accept more data (on output) or when 
>> there is an incoming connection. In practice, you should not need any 
>> delays to be inserted in your program to make it work - if that is 
>> needed, it means that is an error in it (a race condition). If the 
>> program is polling (checking in a loop whether something has already 
>> happened, and then sleeping for a short while), the duration of the 
>> sleep may indeed influence latency, but should not affect correctness 
>> - if it does, there is an error.
>
> In RBaseX I first calculate an MD5 hash that is send to the server and 
> then I check the status byte that is returned by the server.
>
> writeBin(auth, private$conn)
> socketSelect(list(conn))
> Accepted <- readBin(conn, what = "raw", n = 1) == 0
>
> Without the second line, 'Accepted' is always FALSE. With this line it 
> is TRUE.
>
> BaseX provides example API's in several languages. I've looked at 
> several but indeed none uses any form of delay.
> All API's follow the same pattern, calculate a MD5, send it to the 
> server and check the status byte. So the server is not likely to 
> enforce a delay. So there is nothing left but to look for that racing 
> condition ;-(

Without knowing more details, this looks ok. If you have a non-blocking 
connection, and the server produces a response based on the client 
request, the client has to take into account that it takes the server 
some time to produce the response. Right, the sockets are full duplex 
and so could be the communication protocol, but in this case it 
apparently isn't, it is request/response.

Without the second line, there would be a race condition between the 
server sending a response and the client receiving it. With the second 
line, the client waits for the server before it starts receiving. In 
theory, one could be waiting for the response actively in a loop 
(polling), but socketSelect() is better. Both ways would resolve the 
race condition. Adding a single fixed-time wait, instead, would not 
remove the race condition, because one can never be sure that the server 
wouldn't take longer (apart from waiting too long most of the time).

In the example you are waiting only for a single byte. But if the 
response may be longer, one needs to take into account in the client 
that not all bytes of the response may be available right away. One 
would keep receiving the data in a loop, as they become available (e.g. 
socketSelect() would tell), keep appending them to a buffer, and keep 
looking for when they are complete.

Tomas

>
> Ben



More information about the R-devel mailing list