在C#中接收和发送数据

6

我仍在努力改进之前写的内容。现在我遇到了一个接收数据的问题。我有一个程序,使用tcpClient发送字符串到一个指定端口上监听的程序中。它运行良好,所以我决定再次转发数据。

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();
    }
}

有时它能正常工作,但更多时候,我们把它称为“接收器”的设备无法收到我想要发送的内容。我真的不知道出了什么问题。看起来发送方法可能存在问题。以下是接收器输出的示例。
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...
2个回答

6
这里有几个问题:
  1. StreamReader 有一个4kB的缓冲区,在第一次调用 ReadLine() 时会尝试读取尽可能多的数据。结果是,你可能已经在 StreamReader 中有了数据,并且在没有更多数据可用时进入 Poll(),因为它已经被读取。
  2. Poll() 只需要微秒级的时间。等待0.02毫秒的传入数据很可能会返回 false,除非在调用 Poll() 之前就已经有数据。
  3. 你在每次迭代中创建一个新的 StreamReader,这可能会丢弃先前已读取的数据。
如果你只是想读取行并希望有超时和 StreamReader,那么我建议像这样做:
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);
        } 
    }
}

我还不知道这里发生了什么。我并不像我想象中的那样擅长它。你能再解释一下吗?是否有其他更好的选择来接收并转发数据,而不使用StreamReader?这是我第一次尝试写这样的东西,所以我不确定什么是更好或更糟。 - Allek
以上代码的作用是读取行,直到从服务器端关闭流或者读取一行超过100毫秒。至于其他读写选项,这取决于你想要做什么。使用Socket和byte[]是“自然”的接口。 - Gonzalo

1

在追踪幽灵数据之前,请确保数据实际存在于流中。如果始终存在数据,我们可以解决问题,但从逻辑上看,似乎流要么被置空,要么根本没有数据。


似乎这取决于数据输入的速度,而不是每个数据都可以发送,因此大部分数据会丢失。你的回答让我更加仔细地思考了这个问题:> - Allek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接