views:

576

answers:

2

Im still trying to improve a little bit what I wrote before. Now I faced a problem with receiving data. I have a program which I use to send string using tcpClient to a program in which Im listening on a specified port. It works fine so I decided to send data forward one more time

public static void receiveThread()
{
    while (true)
    {
        TcpListener tcpListener = new TcpListener(IPAddress.Any, port);
        tcpListener.Start();

        Console.WriteLine("Waiting for connection...");

        TcpClient tcpClient = tcpListener.AcceptTcpClient();

        Console.WriteLine("Connected with {0}", tcpClient.Client.RemoteEndPoint);

        while (!(tcpClient.Client.Poll(20, SelectMode.SelectRead)))
        {
            NetworkStream networkStream = tcpClient.GetStream();
            StreamReader streamReader = new StreamReader(networkStream);

            data = streamReader.ReadLine();

            if (data != null)
            {
                Console.WriteLine("Received data: {0}", data);
                send(data); // Here Im using send Method
            }
        }
        Console.WriteLine("Dissconnected...\n");
        tcpListener.Stop();
    }
}

/// <summary>
/// Sending data
/// </summary>
/// <param name="data">Data to send</param>
public static void send(string data)
{
    TcpClient tcpClient = new TcpClient();
    try
    {
        tcpClient.Connect(ipAddress, sendPort);
        Console.WriteLine("Connected with {0}", tcpClient.Client.RemoteEndPoint);
    }
    catch (Exception e)
    {
        Console.WriteLine(e);
    }
    if (tcpClient.Connected)
    {
        NetworkStream networkStream = tcpClient.GetStream();
        StreamWriter streamWriter = new StreamWriter(networkStream);
        Console.WriteLine("Messege {0} to {1}", data, tcpClient.Client.RemoteEndPoint);
        streamWriter.WriteLine(data);
        streamWriter.Flush();
        tcpClient.Close();
    }
}

Sometimes it works fine, but more often, lets call it a receiver, can't get what Im trying to send. And I really do not konw what is wrong with it. Looks like there can be a problem with send method. Here is an example of receivers output

Waiting for connection...
Connected with 127.0.0.1:52449
Dissconnected...

Waiting for connection...
Connected with 127.0.0.1:52450
Received data: qweqwe
Dissconnected...

Waiting for connection...
Connected with 127.0.0.1:52451
Dissconnected...

Waiting for connection...
Connected with 127.0.0.1:52452
Dissconnected...

Waiting for connection...
Connected with 127.0.0.1:52453
Received data: zxczx
Dissconnected...

Waiting for connection...
Connected with 127.0.0.1:52454
Dissconnected...

Waiting for connection...
Connected with 127.0.0.1:52455
Received data: aasd
Dissconnected...

Waiting for connection...
Connected with 127.0.0.1:52457
Received data: www
Dissconnected...
+1  A: 

Ensure that the data actually exists on the stream before chasing ghosts. If there is ALWAYS data we can approach the problem, however looking at it logically it appears as though the stream is either being nulled out or there is just no data on it.

Woot4Moo
Seems it depends on how fast the data is incoming and not each of it can be send so most of it is lost. Your answer made me to think more carefull about that :>
Allek
+4  A: 

Several problems here:

  1. StreamReader has a 4kB buffer and will try to read as much as possible in the first call to ReadLine(). The result is that you might have data in the StreamReader and go into Poll() when there's no more data available because it's already been read.
  2. Poll() takes microseconds. Waiting 0.02ms for incoming data is likely to return false unless the data is there before you call Poll().
  3. You create a new StreamReader on every iteration, which might discard data already read in the previous one.

If you're just going to read lines and want a timeout and a StreamReader, I would do something like:

delegate string ReadLineDelegate ();
...
using (NetworkStream networkStream = tcpClient.GetStream()) {
    StreamReader reader = new StreamReader(networkStream);
    ReadLineDelegate rl = new ReadLineDelegate (reader.ReadLine);
    while (true) {
        IAsyncResult ares = rl.BeginInvoke (null, null);
        if (ares.AsyncWaitHandle.WaitOne (100) == false)
            break; // stop after waiting 100ms
        string str = rl.EndInvoke (ares);
        if (str != null) {
            Console.WriteLine ("Received: {0}", str);
            send (str);
        } 
    }
}
Gonzalo
Don't know yet whats going on here. Im not sp good in it as I would like to be. Can you explain a little bit more about this ? and is there any other and better option to receive that data and send it forward without using StreamReader ?? Its my first attempt to write something like that so Im not sure what is better or worse
Allek
What the above code does is reading lines until the stream is closed from the server side or until it takes more than 100ms to read one. As for other options to read/write, it depends on what you want to do. The "natural" interface is to use byte [] with Socket.
Gonzalo