I am working on what should be a simple TCP server application that receives data from a stream and stores it in a list.
I have succeeded in getting the data when it is sent in one message per connection. My problem seems to be when testing it using telnet from the command line. I will start to type and the program will grab one or two characters depending on my typing speed and then won't receive anything from that stream again. I really am at a loss for why. If I put a thread.sleep in the stream.DataAvailable loop then it will get a few more characters but again will stop. Any help is appreciated. My class is as follows:
public class TCPServer
{
private TcpListener listener;
public List<string> messages;
public TCPServer(IPAddress ip, int port)
{
try
{
messages = new List<string>();
listener = new TcpListener(ip, port);
listener.Start();
listener.BeginAcceptTcpClient(ClientConnected, listener);
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
}
private void ClientConnected(IAsyncResult ar)
{
TcpClient client;
try
{
client = listener.EndAcceptTcpClient(ar);
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
return;
}
try
{
NetworkStream stream = client.GetStream();
string message = "";
while (!stream.DataAvailable)
{
}
while (stream.DataAvailable)
{
byte[] readBytes = new byte[65536];
stream.Read(readBytes, 0, readBytes.Length);
message += Encoding.ASCII.GetString(readBytes).TrimEnd('\0');
}
if (message != null)
{
messages.Add(message);
message = "";
}
listener.BeginAcceptTcpClient(ClientConnected, listener);
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
}
public void Stop()
{
listener.Stop();
}
}
So I managed to solve this problem by looking more into the NetworkStream class. In the callback from BeginReceiveTcpClient I extracted the network stream from the tcpclient so I could access the BeginReceive async method. The relevant code is below:
private void ClientConnected(IAsyncResult ar)
{
byte[] readBytes = new byte[65536];
TcpClient client;
try
{
client = listener.EndAcceptTcpClient(ar);
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
return;
}
try
{
NetworkStream stream = client.GetStream();
stream.BeginRead(buffer, 0, buffer.Length, ReadStream, stream);
listener.BeginAcceptTcpClient(ClientConnected, listener);
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
}
private void ReadStream(IAsyncResult ar)
{
try
{
NetworkStream stream = (NetworkStream)ar.AsyncState;
int bytesRead = stream.EndRead(ar);
content += Encoding.ASCII.GetString(buffer, 0, bytesRead);
dataProcessor.ProcessData(messages);
stream.BeginRead(buffer, 0, buffer.Length, ReadStream, stream);
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
}