2

So I have two Ruby programs, they are a client and server sockets programs and they work together exchanging messages. But a C# client does not work. I give MCVE, first the ruby client.

#socketClient.rb
#With thanks to https://code.likeagirl.io/socket-programming-in-ruby-f714131336fd
require "socket"

while sum = $stdin.gets.chomp # Read lines from the socket
  socket = TCPSocket.open("localhost", 3000)

  #puts "Starting the Client..................."

  socket.puts sum
  while message = socket.gets # Read lines from the socket
    puts message.chomp
  end
  socket.close                    # Close the socket
end

#puts "Closing the Client..................."

and the server

#simplestSocketServer.rb
#With thanks to https://code.likeagirl.io/socket-programming-in-ruby-f714131336fd

require "socket"

port = 3000
ipAddress = "127.0.0.1"
server = TCPServer.open(ipAddress, port) # Server would listen on port 3000
loop { # Servers run forever
puts "Starting the Server, accepting connections on port " + port.to_s + "..................."
client_connection = server.accept # Establish client connect connection
begin
    clientText = client_connection.gets.chomp
    puts clientText

    resp = "Acknowledged"
    client_connection.puts("#{clientText}" +  "#{resp}") # Send the answer to the client
    client_connection.puts("Closing the connection with #{client_connection}")
rescue Exception => getException
    puts "#{getException}"
end
client_connection.close      # Disconnect from the client
}

and the C# console program

using System;
using System.Net.Sockets;
using System.Text;


namespace SimplestCSharpRubySocketsClient
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                string ipAddress = "127.0.0.1";
                Int16 portNumber = 3000;

                TcpClient _client; _client = new TcpClient();
                _client.Connect(ipAddress, portNumber);

                System.Console.WriteLine("we have connected, seemingly ...");

                NetworkStream stream;

                stream = _client.GetStream();

                Byte[] sendBytes = Encoding.UTF8.GetBytes("some text");

                System.Console.WriteLine("writing and flushing some bytes ...");
                stream.Write(sendBytes, 0, sendBytes.Length);
                stream.Flush();

                Byte[] recvBytes = new byte[_client.ReceiveBufferSize];
                System.Console.WriteLine("_client.ReceiveBufferSize = " + _client.ReceiveBufferSize);  // <--- this prints 65536

                System.Console.WriteLine("waiting to read bytes ...");
                stream.Read(recvBytes, 0, recvBytes.Length); //<--- hangs here

                System.Console.WriteLine("comething came back ...");
                string result = Encoding.UTF8.GetString(recvBytes);
                string result2 = result.Substring(0, result.LastIndexOf("\r\n"));

                _client.Close();
                _client.Dispose();
                _client = null;
            }
            catch (Exception ex)
            {
                //TODO figure out a better error handler
                throw ex;
            }
        }
    }
}

The C# program connects and writes bytes but when looking to read bytes it just hangs.

And be aware I am running the C# console program in Visual Studio with admin rights. The two ruby programs run in their own separate Windows console windows.

Folding in some feedback, I added another line in the ruby server to output the clientText. And it prints nothing, suggesting the server is not fully receiving the bytes. Is there a termination signal that C# is required to send?

Thanks in advance.

S Meaden
  • 8,050
  • 3
  • 34
  • 65
  • Possible duplicate of [What are some reasons NetworkStream.Read would hang/block?](https://stackoverflow.com/questions/6958255/what-are-some-reasons-networkstream-read-would-hang-block) (i.e. it is probably hanging since Ruby isn't sending anything - https://stackoverflow.com/a/10719399/34092) – mjwills Jan 20 '19 at 23:47
  • @TheGeneral I know it is hanging on the said line because of breakpoints I am setting and also the output. – S Meaden Jan 20 '19 at 23:48
  • As per the below answer, `NetworkStream.Read` was blocking because Ruby was not sending anything (as a result of the earlier `stream.Write` sending invalid data). I'd still suggest you read the above links I provided to ensure you have a correct mental model of what `NetworkStream.Read` is actually doing. – mjwills Jan 20 '19 at 23:55
  • 1
    @mjwills: ok, yes, specifically this answer https://stackoverflow.com/questions/6958255/what-are-some-reasons-networkstream-read-would-hang-block#answer-33100533 – S Meaden Jan 21 '19 at 00:22

1 Answers1

4

The problem here is that the C# client does not send a newline at the end of the string, like the Ruby version does (socket.puts sends a string with a newline at the end).

If you change your sendBytes array to include a \n in the payload like this:

Byte[] sendBytes = Encoding.UTF8.GetBytes("some text\n");

you will see that it prints comething came back ... on the console.

The newline is required because of the following gets in the Ruby server:

clientText = client_connection.gets.chomp
Jyrki
  • 538
  • 1
  • 4
  • 15