Sockets, Arbitrary Ruby and C

I’ve had this small project in mind to write a server which would execute arbitrary ruby. I didn’t want to have a concept of state, so assignment and memory management weren’t a big deal.  It should:

1. Accept a class method, like puts “Hello, world!”
2. Output on the server “Hello, world!”
3. Output on the client “puts “Hello, world!””

I knew GServer existed in the stdlib, but didn’t know how to work it. I saw a neat trick on the peepcode  screencast with Aaron Patterson: download the source tree and ask _that_ your questions, don’t bother with the docs.

I downloaded ruby’s source tree, kind of nervous, and found the GServer implementation using sublime text’s fuzzy search function. The comments said to just inherit from the class and implement the serve method, and all would rock.

I was surprised by how much cleared reading the source and comments were than reading the rdoc that’s generated from those same source and comments. I was reading through the code really happily, learning about GServer, and managed to get the functionality I was looking for in about 20 minutes. If you want to download the code, it’s available on github:

One of the neat things reading the code was that I actually read the implementation of each method, and I noticed something in the start method that got me thinking. There’s a class to create a new TCPServer:

 @tcpServer =,@port) — from GServer.rb

The requires for the class are socket and thread, so I assumed this came from socket. I read socket.rb, though, and I honestly didn’t see a TCPServer definition, so I checked its requires: is a compiled library. I did a quick search for socket.c and found documentation in there that references, but which doesn’t seem to have any implementation that would recognise the name “”.

Socket.c includes rubyserver.h. Reading that, I saw these two lines:

extern VALUE rb_cTCPServer;

void rsock_init_tcpserver(void);

So we’re mentioning a tcpserver in an included library, finally!

From here, I didn’t know where to go.I did a search of the source tree for tcpserver and found tcpserver.c. It also includes rubyserver.h, so presumably somewhere in that include is where the relationship between socket and tcpserver is created, but I can’t see where.

I do see where the class is made, though:

  * Document-class: TCPServer < TCPSocket
  * TCPServer represents a TCP/IP server socket.
  * A simple TCP server may look like:
  * require 'socket'
  * server = 2000 # Server bind to port 2000
  * loop do
  * client = server.accept # Wait for a client to connect
  * client.puts "Hello !"
  * client.puts "Time is #{}"
  * client.close
  * end
  * A more usable server (serving multiple clients):
  * require 'socket'
  * server = 2000
  * loop do
  * Thread.start(server.accept) do |client|
  * client.puts "Hello !"
  * client.puts "Time is #{}"
  * client.close
  * end
  * end
  rb_cTCPServer = rb_define_class("TCPServer", rb_cTCPSocket);
  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", rsock_sock_listen, 1); /* in socket.c */

So, as long as I can get from tcpserver.c through to socket.c, I think I’ll be okay.
Funny how you sometimes wander down paths.

Author: jamandbees

There's just this whole, like, wha? Out there in the world, y'know? The jam and the bees, please.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: