[#7872] Nonblocking socket-connect — "Francis Cianfrocca" <garbagecat10@...>

All, I needed a nonblocking socket connect for my asynchronous-event

18 messages 2006/05/14
[#7873] Re: Nonblocking socket-connect — Tanaka Akira <akr@...17n.org> 2006/05/14

In article <3a94cf510605140559l7baa0205le341dac4f47d424b@mail.gmail.com>,

[#7874] Re: Nonblocking socket-connect — "Francis Cianfrocca" <garbagecat10@...> 2006/05/15

How about introducing the method Socket#set_nonblocking, or alternatively

[#7875] Re: Nonblocking socket-connect — Yukihiro Matsumoto <matz@...> 2006/05/15

Hi,

[#7876] Re: Nonblocking socket-connect — "Francis Cianfrocca" <garbagecat10@...> 2006/05/15

Well, it's ok then. I'm comfortable adding in the nonblocking

[#7877] Re: Nonblocking socket-connect — Yukihiro Matsumoto <matz@...> 2006/05/15

Hi,

Re: Nonblocking accept

From: "Francis Cianfrocca" <garbagecat10@...>
Date: 2006-05-27 02:28:57 UTC
List: ruby-core #7926
Thanks for the patch, I'll test as soon as I can. In regard to datagrams,
what I meant was nonblocking recvfrom. I haven't tried that one yet.

Let me repeat- the performance boost from nonblocking connect is really
great. Thanks again.

On 5/26/06, Tanaka Akira <akr@m17n.org> wrote:
>
> In article <3a94cf510605260529x658e20e1q7d9754266675c3d5@mail.gmail.com>,
>   "Francis Cianfrocca" <garbagecat10@gmail.com> writes:
>
> > Thanks to the Matz and colleagues for adding the *_nonblock functions.
> They
> > have been a huge help. I've already gotten some big performance
> improvements
> > in the EventMachine event-processing library. I thought it was a little
> > strange that accept_nonblock is not available for TCPServer (because it
> > inherits from IO rather than Socket) but it wasn't hard to work around
> that.
> > (Just create a Socket object and call bind and listen on it myself.) The
> > nonblock functions seem to work well with files and unix-domain sockets.
> I
> > haven't tested datagrams yet but will do so shortly.
>
> Since accept is for connection oriented sockets, UDP doesn't need it.
>
> Index: ext/socket/socket.c
> ===================================================================
> RCS file: /src/ruby/ext/socket/socket.c,v
> retrieving revision 1.164
> diff -u -p -r1.164 socket.c
> --- ext/socket/socket.c 25 May 2006 23:43:29 -0000      1.164
> +++ ext/socket/socket.c 27 May 2006 01:52:19 -0000
> @@ -1383,6 +1383,20 @@ tcp_svr_init(argc, argv, sock)
> }
>
> static VALUE
> +s_accept_nonblock(VALUE klass, OpenFile *fptr, struct sockaddr *sockaddr,
> socklen_t *len)
> +{
> +    int fd2;
> +
> +    rb_secure(3);
> +    rb_io_set_nonblock(fptr);
> +    fd2 = accept(fptr->fd, (struct sockaddr*)sockaddr, len);
> +    if (fd2 < 0) {
> +        rb_sys_fail("accept(2)");
> +    }
> +    return init_sock(rb_obj_alloc(klass), fd2);
> +}
> +
> +static VALUE
> s_accept(klass, fd, sockaddr, len)
>      VALUE klass;
>      int fd;
> @@ -1435,6 +1449,49 @@ tcp_accept(sock)
>                     (struct sockaddr*)&from, &fromlen);
> }
>
> +/*
> + * call-seq:
> + *     tcpserver.accept_nonblock => tcpsocket
> + *
> + * Accepts an incoming connection using accept(2) after
> + * O_NONBLOCK is set for the underlying file descriptor.
> + * It returns an accepted TCPSocket for the incoming connection.
> + *
> + * === Example
> + *     require 'socket'
> + *     serv = TCPServer.new(2202)
> + *     begin
> + *       sock = serv.accept_nonblock
> + *     rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EPROTO,
> Errno::EINTR
> + *       IO.select([serv])
> + *       retry
> + *     end
> + *     # sock is an accepted socket.
> + *
> + * Refer to Socket#accept for the exceptions that may be thrown if the
> call
> + * to TCPServer#accept_nonblock fails.
> + *
> + * TCPServer#accept_nonblock may raise any error corresponding to
> accept(2) failure,
> + * including Errno::EAGAIN.
> + *
> + * === See
> + * * TCPServer#accept
> + * * Socket#accept
> + */
> +static VALUE
> +tcp_accept_nonblock(sock)
> +    VALUE sock;
> +{
> +    OpenFile *fptr;
> +    struct sockaddr_storage from;
> +    socklen_t fromlen;
> +
> +    GetOpenFile(sock, fptr);
> +    fromlen = sizeof(from);
> +    return s_accept_nonblock(rb_cTCPSocket, fptr,
> +                             (struct sockaddr *)&from, &fromlen);
> +}
> +
> static VALUE
> tcp_sysaccept(sock)
>      VALUE sock;
> @@ -1925,6 +1982,49 @@ unix_accept(sock)
>                     (struct sockaddr*)&from, &fromlen);
> }
>
> +/*
> + * call-seq:
> + *     unixserver.accept_nonblock => unixsocket
> + *
> + * Accepts an incoming connection using accept(2) after
> + * O_NONBLOCK is set for the underlying file descriptor.
> + * It returns an accepted UNIXSocket for the incoming connection.
> + *
> + * === Example
> + *     require 'socket'
> + *     serv = UNIXServer.new("/tmp/sock")
> + *     begin
> + *       sock = serv.accept_nonblock
> + *     rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EPROTO,
> Errno::EINTR
> + *       IO.select([serv])
> + *       retry
> + *     end
> + *     # sock is an accepted socket.
> + *
> + * Refer to Socket#accept for the exceptions that may be thrown if the
> call
> + * to UNIXServer#accept_nonblock fails.
> + *
> + * UNIXServer#accept_nonblock may raise any error corresponding to
> accept(2) failure,
> + * including Errno::EAGAIN.
> + *
> + * === See
> + * * UNIXServer#accept
> + * * Socket#accept
> + */
> +static VALUE
> +unix_accept_nonblock(sock)
> +    VALUE sock;
> +{
> +    OpenFile *fptr;
> +    struct sockaddr_storage from;
> +    socklen_t fromlen;
> +
> +    GetOpenFile(sock, fptr);
> +    fromlen = sizeof(from);
> +    return s_accept_nonblock(rb_cUNIXSocket, fptr,
> +                             (struct sockaddr *)&from, &fromlen);
> +}
> +
> static VALUE
> unix_sysaccept(sock)
>      VALUE sock;
> @@ -2784,19 +2884,12 @@ sock_accept_nonblock(sock)
>      VALUE sock;
> {
>      OpenFile *fptr;
> -    int fd2;
>      VALUE sock2;
>      char buf[1024];
>      socklen_t len = sizeof buf;
>
>      GetOpenFile(sock, fptr);
> -    rb_io_set_nonblock(fptr);
> -    fd2 = accept(fptr->fd, (struct sockaddr*)buf, &len);
> -    if (fd2 < 0) {
> -        rb_sys_fail("accept(2)");
> -    }
> -    sock2 = init_sock(rb_obj_alloc(rb_cSocket), fd2);
> -
> +    sock2 = s_accept_nonblock(rb_cSocket, fptr, (struct sockaddr *)buf,
> &len);
>      return rb_assoc_new(sock2, rb_str_new(buf, len));
> }
>
> @@ -3414,6 +3507,7 @@ Init_socket()
>      rb_cTCPServer = rb_define_class("TCPServer", rb_cTCPSocket);
>      rb_define_global_const("TCPserver", rb_cTCPServer);
>      rb_define_method(rb_cTCPServer, "accept", tcp_accept, 0);
> +    rb_define_method(rb_cTCPServer, "accept_nonblock",
> tcp_accept_nonblock, 0);
>      rb_define_method(rb_cTCPServer, "sysaccept", tcp_sysaccept, 0);
>      rb_define_method(rb_cTCPServer, "initialize", tcp_svr_init, -1);
>      rb_define_method(rb_cTCPServer, "listen", sock_listen, 1);
> @@ -3442,6 +3536,7 @@ Init_socket()
>      rb_define_global_const("UNIXserver", rb_cUNIXServer);
>      rb_define_method(rb_cUNIXServer, "initialize", unix_svr_init, 1);
>      rb_define_method(rb_cUNIXServer, "accept", unix_accept, 0);
> +    rb_define_method(rb_cUNIXServer, "accept_nonblock",
> unix_accept_nonblock, 0);
>      rb_define_method(rb_cUNIXServer, "sysaccept", unix_sysaccept, 0);
>      rb_define_method(rb_cUNIXServer, "listen", sock_listen, 1);
> #endif
>
> --
> Tanaka Akira
>
>

In This Thread

Prev Next