Client/server with threads

Yow!
I’m trying to make a script that will act as a server (server 1), and
when a connection to the server server 1 is made, it will start a
thread that will connect to another server (server 2), and it will keep
the connection to server 2, even if the client disconnects.

The thing is that, as I’ve tried, my client/server will not connect to
another server, and if it does, the client can not disconnect.

Any ideas?

Thanks,
Andreas


require ‘socket’

class Session < Thread
def initalize(session_id)
super
@session_id = session_id
end

def session_id
@session_id
end

def send_message( message
# This method should send a message to
# server 2
puts message
end
end

threads = []

server = TCPServer.new(“0.0.0.0”, 12121)

while (session = server.accept)
session_id, message = session.gets.split(";", 2)

t = threads.map {|t| t if t[“session_id”] == session_id }.delete_if
{|s| s == nil}.first
puts t
if t
puts “Found thread with existing session_id: #{ session_id }”
t.send :send_message, message
else
threads << Session.new(session) do |t|
Thread.current[“session_id”] = session_id
puts “Creating thread for #{ session_id }”
end
end
session.close
end

On 8/19/06, [email protected] [email protected] wrote:

@session_id = session_id

end
{|s| s == nil}.first
session.close
end

First, make sure your constructor is getting called. You spelled it
“initalize” instead of “initialize”

unknown wrote:

Oh, thanks. :slight_smile: Didn’t see that. :slight_smile:

But, now, there are some problems. The program gets stuck in the loop
on line 12, which I want the program to do in the background. (and it
shouldn’t get stuck) :slight_smile:

Please forgive me, I don’t intend to be rude, but this program is not
well thought out. You should reconsider your use of threads in the first
place. Try an implementation with fork until you get it right. (And fork
after you accept, not after you block on a gets from the accepted
socket.)

I think your program gets “stuck” because you’re executing your loop in
a subclassed constructor. The new thread of control that you think
you’re getting never actually starts running. To prove it, put a print
statement immediately after the accept, and then connect to your program
twice, from two different shells. I predict the second client will
appear to connect (because the TCP server picks it up in the kernel) but
your accept call will not execute more than once.

Francis C. wrote:

place. Try an implementation with fork until you get it right. (And fork
after you accept, not after you block on a gets from the accepted
socket.)

I think your program gets “stuck” because you’re executing your loop in
a subclassed constructor. The new thread of control that you think
you’re getting never actually starts running. To prove it, put a print
statement immediately after the accept, and then connect to your program
twice, from two different shells. I predict the second client will
appear to connect (because the TCP server picks it up in the kernel) but
your accept call will not execute more than once.

Thanks for the advice, and for explaining :slight_smile:
I’ll take a look at fork and see if I can get this working :slight_smile:

Oh, thanks. :slight_smile: Didn’t see that. :slight_smile:

But, now, there are some problems. The program gets stuck in the loop
on line 12, which I want the program to do in the background. (and it
shouldn’t get stuck) :slight_smile:

require ‘socket’

class Session < Thread
def initialize(session)
super
puts session
@session_id, @nick, @channels = session.split(";", 3)
@host = “wowow”
@channels = @channels.split(",")
@connected = 0
@connection = TCPSocket.new(“127.0.0.1”, 12122)
until @connection.closed?
print “a”
if @connected == 0
login
@connected = 1
end
raw = @connection.gets
parse( raw.strip ) unless raw.nil?
end
end

def session_id
@session_id
end

def send_message( message )
puts message
end

def irc_join( channel )
irc_raw( “JOIN #{ channel }” )
end

def irc_nick( nick )
irc_raw( “NICK #{ nick }” )
@nick = nick
end

private

def irc_raw( msg )
@connection.send( “#{ msg }\r\n”, 0 )
end

def login
irc_raw( “NICK #{ @nick }” )
irc_raw( "USER #{ @nick } #{ @nick } #{ @host } : #{ @nick } " )
end

def parse( line )
input = line.split(" ")
if input[0][0].chr == “:”
case input[1]
when “001”
@channels.each {|c| irc_join© }
when “433”
irc_nick( “#{ @nick }_” )
end
end
end

end

threads = []

server = TCPServer.new(“0.0.0.0”, 12121)

while (session = server.accept)
session_id, message = session.gets.split(";", 2)

t = threads.map {|t| t if t[“session_id”] == session_id }.delete_if
{|s| s == nil}.first
puts t
if t
puts “Found thread with existing session_id: #{session_id}”
t.send :send_message, message
else
threads << Session.new("#{session_id};#{message}") do |t|
Thread.current[“session_id”] = session_id
puts “Creating thread for #{ session_id }”
end
end
session.close
end