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

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

···

On 8/19/06, andreas.alin@gmail.com <andreas.alin@gmail.com> wrote:

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

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(c) }
        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

Francis Cianfrocca wrote:

···

On 8/19/06, andreas.alin@gmail.com <andreas.alin@gmail.com> wrote:
> 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
>
>
>

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.

···

--
Posted via http://www.ruby-forum.com/\.

Francis Cianfrocca wrote:

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.

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:

···

--
Posted via http://www.ruby-forum.com/\.