diff --git a/src/ruby/end2end/echo_server.rb b/src/ruby/end2end/end2end_common.rb
similarity index 69%
rename from src/ruby/end2end/echo_server.rb
rename to src/ruby/end2end/end2end_common.rb
index 5e80740aa0ab30370688c3d757832f1e8496116b..67961cdf972cf1f55eba928e951d41ca1fa8c06c 100755
--- a/src/ruby/end2end/echo_server.rb
+++ b/src/ruby/end2end/end2end_common.rb
@@ -38,6 +38,10 @@ $LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir)
 
 require 'grpc'
 require 'echo_services_pb'
+require 'client_control_services_pb'
+require 'socket'
+require 'optparse'
+require 'thread'
 
 # GreeterServer is simple server that implements the Helloworld Greeter server.
 class EchoServerImpl < Echo::EchoServer::Service
@@ -48,17 +52,18 @@ class EchoServerImpl < Echo::EchoServer::Service
 end
 
 class ServerRunner
-  def initialize(port)
-    @port = port
+  def initialize
   end
   def run
     @srv = GRPC::RpcServer.new
+    port = @srv.add_http2_port('0.0.0.0:0', :this_port_is_insecure)
+    @srv.handle(EchoServerImpl)
+
     @thd = Thread.new do
-      @srv.add_http2_port("localhost:#{@port}", :this_port_is_insecure)
-      @srv.handle(EchoServerImpl)
       @srv.run
     end
     @srv.wait_till_running
+    port
   end
   def stop
     @srv.stop
@@ -66,3 +71,32 @@ class ServerRunner
     raise "server not stopped" unless @srv.stopped?
   end
 end
+
+def start_client(client_main, server_port)
+  this_dir = File.expand_path(File.dirname(__FILE__))
+
+  tmp_server = TCPServer.new(0)
+  client_control_port = tmp_server.local_address.ip_port
+  tmp_server.close
+
+  client_path = File.join(this_dir, client_main)
+  client_pid = Process.spawn(RbConfig.ruby, client_path,
+			     "--client_control_port=#{client_control_port}",
+			     "--server_port=#{server_port}")
+  sleep 1
+  control_stub = ClientControl::ClientController::Stub.new("localhost:#{client_control_port}", :this_channel_is_insecure)
+  return control_stub, client_pid
+end
+
+def cleanup(control_stub, server_runner)
+  control_stub.shutdown(ClientControl::Void.new)
+  Process.wait(client_pid)
+
+  client_exit_code = $?.exitstatus
+
+  if client_exit_code != 0
+    raise "term sig test failure: client exit code: #{client_exit_code}"
+  end
+
+  server_runner.stop
+end
diff --git a/src/ruby/end2end/lib/client_control_pb.rb b/src/ruby/end2end/lib/client_control_pb.rb
index 866095a80ac866905e87e6e243b5b261789b05c3..1a938f1b5ae928f9fa5ae868bd5c336d321a2884 100644
--- a/src/ruby/end2end/lib/client_control_pb.rb
+++ b/src/ruby/end2end/lib/client_control_pb.rb
@@ -7,15 +7,11 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
   add_message "client_control.DoEchoRpcRequest" do
     optional :request, :string, 1
   end
-  add_message "client_control.CreateClientStubRequest" do
-    optional :server_address, :string, 1
-  end
   add_message "client_control.Void" do
   end
 end
 
 module ClientControl
   DoEchoRpcRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("client_control.DoEchoRpcRequest").msgclass
-  CreateClientStubRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("client_control.CreateClientStubRequest").msgclass
   Void = Google::Protobuf::DescriptorPool.generated_pool.lookup("client_control.Void").msgclass
 end
diff --git a/src/ruby/end2end/lib/client_control_services_pb.rb b/src/ruby/end2end/lib/client_control_services_pb.rb
index 4c31f3e59004dc391e918b036c9ba5e968c1406c..04b2291bc78fdb409a009c0210575eb944809db8 100644
--- a/src/ruby/end2end/lib/client_control_services_pb.rb
+++ b/src/ruby/end2end/lib/client_control_services_pb.rb
@@ -45,7 +45,6 @@ module ClientControl
       self.service_name = 'client_control.ClientController'
 
       rpc :DoEchoRpc, DoEchoRpcRequest, Void
-      rpc :CreateClientStub, CreateClientStubRequest, Void
       rpc :Shutdown, Void, Void
     end
 
diff --git a/src/ruby/end2end/protos/client_control.proto b/src/ruby/end2end/protos/client_control.proto
index 5e11876cb40e99f6f7f9c9c77c5d7aeea75904bf..f985bb486dcee99cc195f9640cd9e6732a9aa287 100644
--- a/src/ruby/end2end/protos/client_control.proto
+++ b/src/ruby/end2end/protos/client_control.proto
@@ -33,7 +33,6 @@ package client_control;
 
 service ClientController {
   rpc DoEchoRpc (DoEchoRpcRequest) returns (Void) {}
-  rpc CreateClientStub(CreateClientStubRequest) returns (Void) {}
   rpc Shutdown(Void) returns (Void) {}
 }
 
@@ -41,8 +40,4 @@ message DoEchoRpcRequest {
   string request = 1;
 }
 
-message CreateClientStubRequest {
-  string server_address = 1;
-}
-
 message Void{}
diff --git a/src/ruby/end2end/sig_handling_client.rb b/src/ruby/end2end/sig_handling_client.rb
index 860c6b5f0d31385be24dc6c8cc95a730a541414e..f0b2ba61caf84128e742ea629fcaf16576d44ff9 100755
--- a/src/ruby/end2end/sig_handling_client.rb
+++ b/src/ruby/end2end/sig_handling_client.rb
@@ -29,32 +29,18 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-this_dir = File.expand_path(File.dirname(__FILE__))
-protos_lib_dir = File.join(this_dir, 'lib')
-grpc_lib_dir = File.join(File.dirname(this_dir), 'lib')
-$LOAD_PATH.unshift(grpc_lib_dir) unless $LOAD_PATH.include?(grpc_lib_dir)
-$LOAD_PATH.unshift(protos_lib_dir) unless $LOAD_PATH.include?(protos_lib_dir)
-$LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir)
-
-require 'grpc'
-require 'echo_services_pb'
-require 'client_control_services_pb'
-require 'optparse'
-require 'thread'
+require_relative './end2end_common'
 
 class SigHandlingClientController < ClientControl::ClientController::Service
-  def initialize(srv)
+  def initialize(srv, stub)
     @srv = srv
+    @stub = stub
   end
   def do_echo_rpc(req, _)
     response = @stub.echo(Echo::EchoRequest.new(request: req.request))
     raise "bad response" unless response.response == req.request
     ClientControl::Void.new
   end
-  def create_client_stub(req, _)
-    @stub = Echo::EchoServer::Stub.new(req.server_address, :this_channel_is_insecure)
-    ClientControl::Void.new
-  end
   def shutdown(_, _)
     Thread.new do
       #TODO(apolcyn) There is a race between stopping the server and the "shutdown" rpc completing,
@@ -68,10 +54,14 @@ end
 
 def main
   client_control_port = ''
+  server_port = ''
   OptionParser.new do |opts|
     opts.on('--client_control_port=P', String) do |p|
       client_control_port = p
     end
+    opts.on('--server_port=P', String) do |p|
+      server_port = p
+    end
   end.parse!
 
   Signal.trap("TERM") do
@@ -83,8 +73,9 @@ def main
   end
 
   srv = GRPC::RpcServer.new
-  srv.add_http2_port("localhost:#{client_control_port}", :this_port_is_insecure)
-  srv.handle(SigHandlingClientController.new(srv))
+  srv.add_http2_port("0.0.0.0:#{client_control_port}", :this_port_is_insecure)
+  stub = Echo::EchoServer::Stub.new("localhost:#{server_port}", :this_channel_is_insecure)
+  srv.handle(SigHandlingClientController.new(srv, stub))
   srv.run
 end
 
diff --git a/src/ruby/end2end/sig_handling_driver.rb b/src/ruby/end2end/sig_handling_driver.rb
index 524f0cebe8d37f5cfb9a6aea78ddda5220ef9f81..bda5c03c168664249cbecfe27c5eae7d3221ee15 100755
--- a/src/ruby/end2end/sig_handling_driver.rb
+++ b/src/ruby/end2end/sig_handling_driver.rb
@@ -32,39 +32,20 @@
 # smoke test for a grpc-using app that receives and
 # handles process-ending signals
 
-this_dir = File.expand_path(File.dirname(__FILE__))
-protos_lib_dir = File.join(this_dir, 'lib')
-grpc_lib_dir = File.join(File.dirname(this_dir), 'lib')
-$LOAD_PATH.unshift(grpc_lib_dir) unless $LOAD_PATH.include?(grpc_lib_dir)
-$LOAD_PATH.unshift(protos_lib_dir) unless $LOAD_PATH.include?(protos_lib_dir)
-$LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir)
-
-require 'grpc'
-require 'echo_server'
-require 'client_control_services_pb'
+require_relative './end2end_common'
 
 def main
-  this_dir = File.expand_path(File.dirname(__FILE__))
-  lib_dir = File.join(File.dirname(this_dir), 'lib')
-
-  server_port = '50051'
   STDERR.puts "start server"
-  server_runner = ServerRunner.new(server_port)
-  server_runner.run
+  server_runner = ServerRunner.new
+  server_port = server_runner.run
 
   sleep 1
 
-  client_control_port = '50052'
-
   STDERR.puts "start client"
-  client_path = File.join(this_dir, "sig_handling_client.rb")
-  client_pid = Process.spawn(RbConfig.ruby, client_path, "--client_control_port=#{client_control_port}")
-  control_stub = ClientControl::ClientController::Stub.new("localhost:#{client_control_port}", :this_channel_is_insecure)
+  control_stub, client_pid = start_client("sig_handling_client.rb", server_port)
 
   sleep 1
 
-  control_stub.create_client_stub(ClientControl::CreateClientStubRequest.new(server_address: "localhost:#{server_port}"))
-
   count = 0
   while count < 5
     control_stub.do_echo_rpc(ClientControl::DoEchoRpcRequest.new(request: 'hello'))
@@ -73,16 +54,7 @@ def main
     count += 1
   end
 
-  control_stub.shutdown(ClientControl::Void.new)
-  Process.wait(client_pid)
-
-  client_exit_code = $?.exitstatus
-
-  if client_exit_code != 0
-    raise "term sig test failure: client exit code: #{client_exit_code}"
-  end
-
-  server_runner.stop
+  cleanup(control_stub, server_runner)
 end
 
 main