Ben Sharpe
Ben Sharpe

Reputation: 799

Connecting to a TCP server unable to get response

I have a TCP client that successfully connects to an external Server and I am sending a request to the server which is received successfully.

However when I try and receive the response it just stalls and never receives it.

var message = "Hello World!";
var port = 9999; //Changed for question
var ip = "100.100.100.100"; //Changed for question
var tcpclnt = new TcpClient();

Console.WriteLine("Connecting.....");

await tcpclnt.ConnectAsync(ip, port);

Console.WriteLine("Connected");

Stream stm = tcpclnt.GetStream();

byte[] ba = Encoding.ASCII.GetBytes(message);

Console.WriteLine("Transmitting {0}", message);
await stm.WriteAsync(ba, 0, ba.Length);

byte[] bb = new byte[100];
var bytesRecieved = await stm.ReadAsync(bb, 0, 100);

var response = new StringBuilder();

foreach (byte t in bb)
      response.Append(Convert.ToChar(t));

Console.WriteLine("Received {0}", response);

tcpclnt.Close();

I have the correct port open on my computer and on my router.

Upvotes: 2

Views: 1161

Answers (1)

Luaan
Luaan

Reputation: 63772

There's many things wrong with your code, but one of the biggies is that the other side has no way of knowing when you're done transmitting.

TCP is a stream-based protocol, not a message-based one. That means that there's no 1:1 mapping between sends on one side, and reads on the other. It's like writing and reading a file stream, not like sending e-mail.

This among other things means that unless you're actually working with streamed data, you'll need some way to distinguish messages in the stream from each other. For example, by adding \r\n to each of your strings - but that's something the client and the server have to agree on. You'll have to also show the server code if you want more specific help.

As for the other mistakes:

  • You can't igore the return value of ReadAsync - it tells you how much data was actually read.
  • You can't just wave-away the encoding issues - both sides have to explicitly use an (agreed upon) encoding for writing and reading. In your case, this would mean using Encoding.ASCII.GetString instead of Convert.ToChar.
  • Related to the first point, you can't just call ReadAsync once and expect to get the whole message (or even expect to get exactly one message). For anything realistic, you'll need a loop, reading data as long as there is some.
  • No handling of graceful shutdown. Not important if you're only doing HTTP-style "request -> response", but problematic otherwise.

Upvotes: 2

Related Questions