librelist archives

« back to archive

Using Kgio::TCPSocket.start with EventMachine (in non blocking way)

Using Kgio::TCPSocket.start with EventMachine (in non blocking way)

From:
Iñaki Baz Castillo
Date:
2012-04-06 @ 14:47
Hi, I need to use Ruby OpenSSL bindings in a TLS client connection
made from EventMachine, so I should use EM.attach by providing it the
previously created TCP socket and set notify_readable/writable.

Now the first issue is: how to do a non-blocking TCP connection
(needed within EM environment)? So I found
"Kgio::TCPSocket.start('127.0.0.1', 80)":

---------------------------------------------------------------
Creates a new Kgio::TCPSocket object and initiates a non-blocking
connection. The caller should select/poll on the socket for
writability before attempting to write or optimistically attempt a
write and handle :wait_writable or Errno::EAGAIN.
---------------------------------------------------------------

I basically need a callback "on_connected" to be called when such a
TCP connection is completed, but honestly I have no idea since it
seems to require using select/poll (at Ruby level) working on top of a
EventMachine code, really complex IMHO. Or maybe I miss something.

Could I get some help please?

Thanks a lot.

-- 
Iñaki Baz Castillo
<ibc@aliax.net>

Re: [kgio] Using Kgio::TCPSocket.start with EventMachine (in non blocking way)

From:
Eric Wong
Date:
2012-04-09 @ 03:17
Iñaki Baz Castillo <ibc@aliax.net> wrote:
> Now the first issue is: how to do a non-blocking TCP connection
> (needed within EM environment)? So I found
> "Kgio::TCPSocket.start('127.0.0.1', 80)":

> I basically need a callback "on_connected" to be called when such a
> TCP connection is completed, but honestly I have no idea since it
> seems to require using select/poll (at Ruby level) working on top of a
> EventMachine code, really complex IMHO. Or maybe I miss something.

Kgio::TCPSocket.start is correct.  I'm not sure what you need the
"on_connected" callback for, but you can just do whatever you want
to do on the initial write.  You can keep track of the initial write
vs subsequent writes with an instance variable.

Just try writing, and if you get :wait_writable, tell EM to have it
watch for writability somehow.


  sock = Kgio::TCPSocket.start(...)
  buf = "TEST"
  case buf = sock.kgio_trywrite(buf)
  when :wait_writable
    # Tell EM to wait for sock to be writable
    # It's been a while since I've used EM
    # so I'm not familiar with the API anymore.
  when nil
    # initial write completed

    # otherwise, keep looping if we have an unwritten string
    # (we'll probably hit :wait_writable at the next iteration)
  end while String === buf

Re: [kgio] Using Kgio::TCPSocket.start with EventMachine (in non blocking way)

From:
Iñaki Baz Castillo
Date:
2012-04-09 @ 18:12
2012/4/9 Eric Wong <normalperson@yhbt.net>:
> Kgio::TCPSocket.start is correct.  I'm not sure what you need the
> "on_connected" callback for, but you can just do whatever you want
> to do on the initial write.  You can keep track of the initial write
> vs subsequent writes with an instance variable.
>
> Just try writing, and if you get :wait_writable, tell EM to have it
> watch for writability somehow.
>
>
>  sock = Kgio::TCPSocket.start(...)
>  buf = "TEST"
>  case buf = sock.kgio_trywrite(buf)
>  when :wait_writable
>    # Tell EM to wait for sock to be writable
>    # It's been a while since I've used EM
>    # so I'm not familiar with the API anymore.
>  when nil
>    # initial write completed
>
>    # otherwise, keep looping if we have an unwritten string
>    # (we'll probably hit :wait_writable at the next iteration)
>  end while String === buf


Thanks Eric, really useful. Let me just a question:

Could it be some other case in which kgio_trywrite returns != nil
*after* connection has been properly established?


-- 
Iñaki Baz Castillo
<ibc@aliax.net>

Re: [kgio] Using Kgio::TCPSocket.start with EventMachine (in non blocking way)

From:
Iñaki Baz Castillo
Date:
2012-04-10 @ 12:35
2012/4/9 Iñaki Baz Castillo <ibc@aliax.net>:
> Could it be some other case in which kgio_trywrite returns != nil
> *after* connection has been properly established?

This is, could it occur that kgio_trywrite() returns :wait_writable
*after* the connection was successfully established and data already
sent or received?

-- 
Iñaki Baz Castillo
<ibc@aliax.net>

Re: [kgio] Using Kgio::TCPSocket.start with EventMachine (in non blocking way)

From:
Eric Wong
Date:
2012-04-10 @ 20:09
Iñaki Baz Castillo <ibc@aliax.net> wrote:
> 2012/4/9 Iñaki Baz Castillo <ibc@aliax.net>:
> > Could it be some other case in which kgio_trywrite returns != nil
> > *after* connection has been properly established?
> 
> This is, could it occur that kgio_trywrite() returns :wait_writable
> *after* the connection was successfully established and data already
> sent or received?

Yes, socket buffers can be filled up if the reader can't read fast
enough.  Sometimes the write() is partial before this happens (and the
kernel may internally allocate more memory for socket buffers in this
case).

Re: [kgio] Using Kgio::TCPSocket.start with EventMachine (in non blocking way)

From:
Iñaki Baz Castillo
Date:
2012-04-10 @ 20:56
2012/4/10 Eric Wong <normalperson@yhbt.net>:
> Iñaki Baz Castillo <ibc@aliax.net> wrote:
>>
>> This is, could it occur that kgio_trywrite() returns :wait_writable
>> *after* the connection was successfully established and data already
>> sent or received?
>
> Yes, socket buffers can be filled up if the reader can't read fast
> enough.  Sometimes the write() is partial before this happens (and the
> kernel may internally allocate more memory for socket buffers in this
> case).

Good to know. Ok, my code is ready for that ;)

-- 
Iñaki Baz Castillo
<ibc@aliax.net>

Using Kgio::TCPSocket.start with EventMachine (in non blocking way)

From:
Iñaki Baz Castillo
Date:
2012-04-06 @ 15:10
Hi, I need to use Ruby OpenSSL bindings in a TLS client connection
made from EventMachine, so I should use EM.attach by providing it the
previously created TCP socket and set notify_readable/writable.

Now the first issue is: how to do a non-blocking TCP connection
(needed within EM environment)? So I found
"Kgio::TCPSocket.start('127.0.0.1', 80)":

---------------------------------------------------------------
Creates a new Kgio::TCPSocket object and initiates a non-blocking
connection. The caller should select/poll on the socket for
writability before attempting to write or optimistically attempt a
write and handle :wait_writable or Errno::EAGAIN.
---------------------------------------------------------------

I basically need a callback "on_connected" to be called when such a
TCP connection is completed, but honestly I have no idea since it
seems to require using select/poll (at Ruby level) working on top of a
EventMachine code, really complex IMHO. Or maybe I miss something.

Could I get some help please?

Thanks a lot.


-- 
Iñaki Baz Castillo
<ibc@aliax.net>