我想通过TCP将数据发送到特定的IP \端口
我写了一个示例,该示例应该发送一些字符串:

internal class TcpSender : BaseDataSender
{
    public TcpSender(Settings settings) : base(settings)
    {
    }

    public async override Task SendDataAsync(string data)
    {
        Guard.ArgumentNotNullOrEmptyString(data, nameof(data));

        byte[] sendData = Encoding.UTF8.GetBytes(data);
        using (var client = new TcpClient(Settings.IpAddress, Settings.Port))
        using (var stream = client.GetStream())
        {
            await stream.WriteAsync(sendData, 0, sendData.Length);
        }
    }
}


这里的问题是,我的流在tcp客户端发送所有数据之前已被丢弃。我应该如何重写我的代码以等待所有数据被写入并且仅在处置完所有资源之后?谢谢

UPD:从控制台实用程序调用:

static void Main(string[] args)
{
    // here settings and date are gotten from args
    try
    {
        GenerateAndSendData(settings, date)
                .GetAwaiter()
                .GetResult();
    }
    catch (Exception e)
    {
        Console.ForegroundColor = ConsoleColor.Red;
        Console.WriteLine(e);
    }
}

public static async Task GenerateAndSendData(Settings settings, DateTime date)
{
    var sender = new TcpSender(settings);
    await sender.SendDataAsync("Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.");
}


Upd2:Echo服务器代码(从某些stackoverflow问题中被盗):

class TcpEchoServer
{
    static TcpListener listen;
    static Thread serverthread;

    public static void Start()
    {
        listen = new TcpListener(System.Net.IPAddress.Parse("127.0.0.1"), 514);
        serverthread = new Thread(new ThreadStart(DoListen));
        serverthread.Start();
    }

    private static void DoListen()
    {
        // Listen
        listen.Start();
        Console.WriteLine("Server: Started server");

        while (true)
        {
            Console.WriteLine("Server: Waiting...");
            TcpClient client = listen.AcceptTcpClient();
            Console.WriteLine("Server: Waited");

            // New thread with client
            Thread clientThread = new Thread(new ParameterizedThreadStart(DoClient));
            clientThread.Start(client);
        }
    }

    private static void DoClient(object client)
    {
        // Read data
        TcpClient tClient = (TcpClient)client;

        Console.WriteLine("Client (Thread: {0}): Connected!", Thread.CurrentThread.ManagedThreadId);
        do
        {
            if (!tClient.Connected)
            {
                tClient.Close();
                Thread.CurrentThread.Abort();       // Kill thread.
            }

            if (tClient.Available > 0)
            {
                byte pByte = (byte)tClient.GetStream().ReadByte();
                Console.WriteLine("Client (Thread: {0}): Data {1}", Thread.CurrentThread.ManagedThreadId, pByte);
                tClient.GetStream().WriteByte(pByte);
            }

            // Pause
            Thread.Sleep(100);
        } while (true);
    }
}

最佳答案

最简单的部分是,回显服务器工作缓慢,因为它在每次读取后会暂停100毫秒。我想那是为了让您有机会看到正在发生的事情。

对于为什么看不到所有数据的原因,我不确定是否确切,但是我认为可能正在发生的事情是:


当您的客户端执行离开using块时,将处理流(感谢Craig.Feied在他的answer中指出执行在底层套接字完成数据的物理传输之前执行)
处置NetworkStream会导致它关闭基础Socket
关机使Socket有机会在最终关闭之前完成所有缓冲数据的发送。参考:Graceful Shutdown, Linger Options, and Socket Closure
注意,由于NetworkStream本身没有缓冲任何数据,因为它直接将所有写入传递给套接字。因此,即使在传输完成之前就丢弃了NetworkStream,也不会丢失任何数据
处于关闭状态的套接字可以完成现有请求,但不接受新请求。


因此,您的回显服务器从已经进行的传输中接收数据(好的),但是随后在连接上发出了新的写入请求(不好)。我怀疑这种写入导致回声服务器提前退出而没有读取所有数据。要么:


客户端关闭连接,因为它收到了不期望的数据,或者
回显服务器在tClient.GetStream().WriteByte(pByte);上引发未捕获的异常


应该很容易检查是否确实是以上两种情况之一。

关于c# - 使TcpClient等待数据写入,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52815825/

10-12 12:48
查看更多