From: Daniel Martin Date: 2006-09-06T20:51:00+09:00 Subject: Re: Total newbie, but I think I found a bug in Socket? Patrick Toomey writes: > Good analysis of where the problem is. Tell me, does this ruby script work on your two environments? # In one script, start this first require 'socket' include Socket::Constants sockaddrinfo = Socket.getaddrinfo( 'localhost', 2200, AF_INET, SOCK_STREAM )[0] socket = Socket.new( *sockaddrinfo[4..6] ) sockaddr = Socket.pack_sockaddr_in( sockaddrinfo[1], sockaddrinfo[3] ) socket.bind( sockaddr ) socket.listen( 5 ) client, client_sockaddr = socket.accept puts "The client said, '#{client.readline.chomp}'" client.puts "Hello from script one!" socket.close The trouble, as most responses have pointed out, is that OS X translates "localhost" by default into an IP6 address, whereas your socket is initially set to be an IPv4 socket (when you use AF_INET in your Socket.new call). Now in actuality, OS X translates "localhost" into several different addresses, and you can see them all by running this script: require 'socket' def find_const(i,p) Socket.constants.select{|n|n=~p}.each{ |n| return "Socket::#{n}" if i == Socket.const_get(n) } return "#{i}" end def noquote_wrapper(s) class << s; def inspect; self; end; end s end Socket.getaddrinfo('localhost',nil).each{|a| a[4]=noquote_wrapper find_const(a[4],/^AF_/) a[5]=noquote_wrapper find_const(a[5],/^SOCK_/) a[6]=noquote_wrapper find_const(a[6],/^IPPROTO_/) p a } The improved server script I have up above works by explicitly requesting only the SOCK_STREAM / AF_INET address, and then using the returned values in the Socket.new call, rather than using potentially mismatched values for the socket's address family specified in the "new" call and the address returned from pack_sockaddr_in. Note that when calling pack_sockaddr_in it also passes that call the IP address rather than the hostname. -- s=%q( Daniel Martin -- martin@snowplow.org puts "s=%q(#{s})",s.map{|i|i}[1] ) puts "s=%q(#{s})",s.map{|i|i}[1]