簡體   English   中英

StreamWriter ReadLine方法掛起程序

[英]StreamWriter ReadLine method hangs program

我正在嘗試在C#中使用一些基本的多線程。 我沒有找到明確的教程,因此請遵循以下標准代碼:

class Program
{
    private static TcpListener listener;
    private static List<TcpClient> clients; 
    static void Main(string[] args)
    {
        listener = new TcpListener(IPAddress.Any, 1337);
        clients = new List<TcpClient>();
        StartListening();
        Console.WriteLine("Accepting clients..");
        Console.WriteLine("Press any key to exit");
        Console.ReadKey();
    }

    static async void StartListening()
    {
        listener.Start();
        while (true)
        {
            clients.Add(await listener.AcceptTcpClientAsync().ConfigureAwait(false));
            Console.WriteLine("Client connected!");
            HandleClient(clients[clients.Count - 1], clients.Count);
        }
    }

    static async void HandleClient(TcpClient c, int number)
    {
        Console.WriteLine($"Getting client #{number}'s handshake..");
        var ns = c.GetStream();
        var sr = new StreamReader(ns);
        var handshake = sr.ReadLine();
        Console.WriteLine("Client {0}'s handshake: {1}", number, handshake);
    }
}

是的,因此我要在服務器程序中實現的目標是:

 1. Accepting client
 2. Receiving handshake, print it to console
 3. Add to the clients list

接受客戶端的部分起作用,但是該程序僅在HandleClient()的第一行之后停止。 我嘗試過等待荒謬的時間(1000毫秒),即使那樣它什么也沒收到,也不會拋出異常(即保持連接狀態)。 我在這里做錯了什么?

如果需要,客戶端代碼在這里

您的客戶端代碼在這里已損壞-您永遠不會刷新它:

var sw = new StreamWriter(ns);
Thread.Sleep(1000);
sw.WriteLine(handshake);

不需要Thread.Sleep調用,但如果希望將數據立即立即實際發送到網絡層,則應刷新StreamWriter

sw.Flush();

盡管(如Stephen Cleary所指出的那樣)這並不意味着它一定要立即發送,但可以合理地期望它在刷新后“合理地盡快”發送。

我正在嘗試在C#中使用一些基本的多線程。

我總是對嘗試通過編寫裸機TCP / IP服務器來學習並發性的開發人員感到驚訝(以前他們從未對TCP / IP進行過編程)。 並發和TCP / IP是兩個非常困難的主題; 試圖同時學習它們幾乎肯定會以災難告終。 這種方法如此普遍真是奇怪。

如果您想學習異步,我推薦我的async介紹關於最佳實踐的文章 (除其他外,您將學習“避免async void ”原則)。

如果您想學習TCP / IP,我推薦我的TCP / IP .NET FAQ博客系列 但是,幾乎不需要編寫TCP / IP代碼,並且由於您可以更改客戶端和服務器,因此我強烈建議改用SignalR。

我懷疑您實際上是想學習async ,而TCP / IP才剛剛開始。 因此,請刪除較難的主題(TCP / IP),並將async與更簡單的通信(例如WebAPI或SignalR)一起使用。

(就您所看到的實際問題而言,它確實是由緩沖引起的,但是需要注意的是,刷新緩沖區不會導致數據立即通過網絡發送;它只會立即發送到網絡 。適當的解決方案將需要消息框架。)

正如喬恩·斯基特(Jon Skeet)所提到的,要確保內容不僅僅位於緩沖區中,您應該刷新它。

您的客戶應如下所示:

var sw = new StreamWriter(ns);
Thread.Sleep(1000); // let the server catch up
sw.WriteLine(handshake);
sw.Flush();
Console.WriteLine("Staying connected.. Press ESCAPE to exit.");

編輯:忘記提及... Thread.Sleep(1000); 在那里...您可以安全地將其刪除。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM