C# 用C语言接收和发送数据#

C# 用C语言接收和发送数据#,c#,tcpclient,tcplistener,C#,Tcpclient,Tcplistener,我仍然在努力改进我以前写的东西。 现在我面临着接收数据的问题。我有一个程序,我使用tcpClient将字符串发送到一个程序,在该程序中,我在一个指定的端口上侦听。它工作正常,所以我决定再向前发送一次数据 public static void receiveThread() { while (true) { TcpListener tcpListener = new TcpListener(IPAddress.Any, port); tcpListe

我仍然在努力改进我以前写的东西。 现在我面临着接收数据的问题。我有一个程序,我使用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();
    }
}

在追踪重影之前,请确保流中实际存在数据。如果总是有数据,我们可以解决这个问题,但是从逻辑上看,似乎流要么被清空,要么就是没有数据。

这里有几个问题:

  • StreamReader
    有一个4kB的缓冲区,将在第一次调用
    ReadLine()
    时尝试读取尽可能多的内容。结果是,您可能在StreamReader中有数据,并且在没有更多可用数据时进入Poll(),因为它已经被读取
  • Poll()
    需要几微秒。等待0.02ms传入数据很可能返回false,除非在调用
    Poll()
    之前数据已经存在
  • 在每次迭代中创建一个新的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的情况下转发??这是我第一次尝试写这样的东西,所以我不确定上面的代码做的是什么,直到从服务器端关闭流,或者直到读一行需要100毫秒以上。至于其他的读/写选项,这取决于你想做什么。“自然”接口是将字节[]与套接字一起使用。
    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);
            } 
        }
    }