iT邦幫忙

1

C# 為何server先連client後連tcpClient.Available會是0?

  • 分享至 

  • xImage
while (true)
            {
                if (tcpListener.Pending() == false)
                {
                    //...省略
                }
                else
                {
                    tcpClient = tcpListener.AcceptTcpClient();
                    NetworkStream stream = tcpClient.GetStream();

                    bool closed = false;
                    byte[] testByte = new byte[1];
                    
                    while (tcpClient.Connected && !closed)
                    {
                        if (tcpClient.Available > 0)
                        {
                            //讀資料...
                        }
                        try
                        {
                            if (tcpClient.Connected && tcpClient.Client.Poll(30, SelectMode.SelectRead))
                                closed = tcpClient.Client.Receive(testByte, SocketFlags.Peek) == 0;
                        }
                        catch(Exception ex)
                        {
                            closed = true;
                        }
                        Thread.Sleep(20);
                    }
                    stream.Close();
                }
            }

https://ithelp.ithome.com.tw/upload/images/20230118/20141745o2NGOUQIQQ.jpg
請問一下前輩為何這樣的作法,當server端先連線127.0.0.1 ,client後連線,tcpClient.Available會一直為0,可是雙方卻是連線正常,但是當client先嘗試持續連線連上後,server在連上雙方持續一來一往溝通就都正常為何呢?也就是說另一方面,我也希望在server與client正常連接後,client斷線後,client再連上會是正常往來溝通

powerc iT邦新手 1 級 ‧ 2023-01-18 09:22:28 檢舉
我猜是因為tcpClient這個物件不會自己更新吧? 所以狀態還是當初初始給值的狀態。
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

0
JamesDoge
iT邦高手 1 級 ‧ 2023-01-25 06:32:49

1.改用 NetworkStream.DataAvailable 屬性來檢查是否有資料可供讀取,而不是使用 tcpClient.Available。
2.改用 SelectMode.SelectRead 代替 SelectMode.SelectWrite 可以更好地檢查是否有資料可讀取。
3.有可能是由於你的等待時間不足,因此資料尚未完全進入網路串流,所以在 client 連接到 server 後,等待一段時間,再進行讀取。

while (true)
{
    if (tcpListener.Pending() == false)
    {
        // ...省略
    }
    else
    {
        tcpClient = tcpListener.AcceptTcpClient();
        NetworkStream stream = tcpClient.GetStream();

        bool closed = false;
        byte[] testByte = new byte[1];

        // 等待一段時間,以確保資料已進入網路串流
        Thread.Sleep(1000);         
        while (tcpClient.Connected && !closed)
        {
            if (stream.DataAvailable)
            {
                // 讀資料...
            }
            try
            {
				 // 檢查是否有資料可以讀取, 使用 SelectMode.SelectRead 代替 SelectMode.SelectWrite 可以更好地檢查是否有資料可讀取。
                if (tcpClient.Connected && tcpClient.Client.Poll(30, SelectMode.SelectRead))	
				{				
                    int receivedByte = tcpClient.Client.Receive(testByte, SocketFlags.Peek);
                    if (receivedByte == 0)
                        closed = true;
				}
            }
            catch (Exception ex)
            {
                closed = true;
            }
            Thread.Sleep(20);
        }
        stream.Close();
    }
}
rabbit iT邦新手 4 級 ‧ 2023-01-30 14:32:58 檢舉

很感謝你的回答,我server先連,client後連,得到false,client有持續送資料https://ithelp.ithome.com.tw/upload/images/20230130/20141745gRoZtQ9snW.jpg

JamesDoge iT邦高手 1 級 ‧ 2023-01-31 08:16:37 檢舉

HI~我又補充了 請參考

rabbit iT邦新手 4 級 ‧ 2023-02-02 10:02:48 檢舉

你好,其實Socket.Poll 方法中三種我都試過Read,Write,Error,得到效果都室有連client但是client持續送資料都收到0或false,但是client先連server後連就正常,感覺三種怎麼調都沒效果才發問

我要發表回答

立即登入回答