none
TCPClient在WIN 10及WIN Server 2016被斷線 RRS feed

  • 問題

  • 各位先進大家好,小弟利用Socket簡單寫了一支溝通程式,在WIN 7及Windows Server 2008上執行都沒有問題,但是在WIN 10及Windows Server 2016上執行時,只要一連線就馬上被斷線(Connected=false),死在以下這行
    networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);
    ,因為連線已斷,所以無法從clientSocket取出資料而死,請問各位先進有遇到這樣的現像嗎?謝謝回覆.

    //Client 端 Windows Form Source code,
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Net.Sockets;
    using System.Threading;

    namespace ClientSocket
    {
        public partial class Form1 : Form
        {
            System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient();
            NetworkStream serverStream = default(NetworkStream);
            string readData = null;

            public Form1()
            {
                InitializeComponent();
            }

            private void button1_Click(object sender, EventArgs e)
            {
                byte[] outStream = System.Text.Encoding.ASCII.GetBytes(textBox2.Text + "$");
                serverStream.Write(outStream, 0, outStream.Length);
                serverStream.Flush();
            }

            private void button2_Click(object sender, EventArgs e)
            {
                readData = "Conected to Chat Server ...";
                msg();
                clientSocket.Connect("127.0.0.1", 10720);
                serverStream = clientSocket.GetStream();

                byte[] outStream = System.Text.Encoding.ASCII.GetBytes(textBox3.Text + "$");
                serverStream.Write(outStream, 0, outStream.Length);
                serverStream.Flush();

                Thread ctThread = new Thread(getMessage);
                ctThread.Start();
            }

                private void getMessage()
                {
                    try
                    {
                        while (true)
                        {
                            serverStream = clientSocket.GetStream();
                            int buffSize = 0;
                            byte[] inStream = new byte[10025];
                            buffSize = clientSocket.ReceiveBufferSize;
                            serverStream.Read(inStream, 0, buffSize);
                            string returndata = System.Text.Encoding.ASCII.GetString(inStream);
                            readData = "" + returndata;
                            msg();
                        }
                    }
                    catch (Exception ex)
                    {
                        if (clientSocket.Connected != false)//如果連線已斷,則離開
                        {
                            serverStream.Close();
                            clientSocket.Close();
                            //this.Close();
                        }
                    }
                }

                private void msg()
                {
                    if (this.InvokeRequired)
                        this.Invoke(new MethodInvoker(msg));
                    else
                        textBox1.Text = textBox1.Text + Environment.NewLine + " >> " + readData;
                }

        }
    }


    //Server 端 Console Source Code
    using System;
    using System.Threading;
    using System.Net.Sockets;
    using System.Text;
    using System.Collections;

    namespace ServerSocket
    {
        class Program
        {
            public static Hashtable clientsList = new Hashtable();//儲存目前連線的Client物件

            static void Main(string[] args)
            {
                TcpListener serverSocket = new TcpListener(10720);//只負責監聽
                TcpClient clientSocket = default(TcpClient);            
                int counter = 0;

                serverSocket.Start();//開始監聽
                Console.WriteLine("Chat Server Started ....");
                counter = 0;
                while ((true))//監聽循環的開始(不是很明白為什麼While的動作會在此作循環,而只有Socket收到要求時,才會觸發.)
                {
                    counter += 1;
                    clientSocket = serverSocket.AcceptTcpClient();
                    clientSocket.NoDelay = false;
                    byte[] bytesFrom = new byte[10025];
                    string dataFromClient = null;
                    NetworkStream networkStream = clientSocket.GetStream();
                    networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);
                    dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
                    dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
                    clientsList.Add(dataFromClient, clientSocket);//儲存Client Socket
                    broadcast(dataFromClient + " Joined ", dataFromClient, false);//廣播Client已連線資訊
                    Console.WriteLine(dataFromClient + " Joined chat room ");
                    handleClinet client = new handleClinet();
                    client.startClient(clientSocket, dataFromClient, clientsList);//啟動Client Thread
                }
                //以下程式碼因為監聽的循環,所以不可能執行到
                clientSocket.Close();
                serverSocket.Stop();
                Console.WriteLine("exit");
                Console.ReadLine();
            }

            public static void broadcast(string msg, string uName, bool flag)
            {
                foreach (DictionaryEntry Item in clientsList)//逐Client取出
                {
                    TcpClient broadcastSocket;
                    broadcastSocket = (TcpClient)Item.Value;
                    NetworkStream broadcastStream = broadcastSocket.GetStream();
                    Byte[] broadcastBytes = null;

                    if (flag == true)
                    {
                        broadcastBytes = Encoding.ASCII.GetBytes(uName + " says : " + msg);
                    }
                    else
                    {
                        broadcastBytes = Encoding.ASCII.GetBytes(msg);
                    }

                    broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                    broadcastStream.Flush();
                }
            }  //end broadcast function
        }//end Main class


        public class handleClinet
        {
            TcpClient clientSocket;
            string clNo;
            Hashtable clientsList;

            public void startClient(TcpClient inClientSocket, string clineNo, Hashtable cList)
            {
                this.clientSocket = inClientSocket;
                this.clNo = clineNo;
                this.clientsList = cList;
                Thread ctThread = new Thread(doChat);//建立Thread及指定呼叫的Function
                ctThread.Start();//啟動Thread
            }

            private void doChat()
            {
                int requestCount = 0;
                byte[] bytesFrom = new byte[10025];
                string dataFromClient = null;
                Byte[] sendBytes = null;
                string serverResponse = null;
                string rCount = null;
                requestCount = 0;
                while ((true))
                {
                    try
                    {
                        requestCount = requestCount + 1;//接收次數加1
                        NetworkStream networkStream = clientSocket.GetStream();//取得networkStream物件,其中已存在接收到的資訊
                        networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);//將資訊轉為byte儲存到bytesFrom中
                        dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);//轉為字串
                        dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));//去除結束字元
                        Console.WriteLine("From client - " + clNo + " : " + dataFromClient);
                        rCount = Convert.ToString(requestCount);//不明白這行目的為何
                        Program.broadcast(dataFromClient, clNo, true);//要求廣播
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.ToString());
                    }
                }//end while
            }//end doChat
        } //end class handleClinet
    }

    2019年3月28日 上午 11:17

解答

  • 你的位元組陣列並未宣告為緩衝區大小: 

    byte[] bytesFrom = new byte[10025];

    參考這篇:

    [.Net] 資料接收的常識

    宣告 緩衝Byte陣列(接收緩衝區大小)
    緩衝區內位元組數 = 物件.Read(緩衝Byte陣列, 0, 接收緩衝區大小)


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    • 已標示為解答 WilsonFan 2019年4月1日 上午 07:14
    2019年3月29日 下午 01:38

所有回覆

  • Win8 以後防火牆變得比較複雜,你先試試把防火牆含防毒軟體的全關以後試試。

    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    2019年3月28日 上午 11:34
  • 感謝您的回覆,有試過將防火牆,防毒軟體及公司IVanti軟體都關閉了,測試結果仍是相同,謝謝.
    2019年3月29日 上午 01:30
  • 經過不斷的測試,終於發現只要將networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);修改為networkStream.Read(bytesFrom, 0, bytesFrom.Length);就可以正常溝通了,但是我依然不明白為什麼一執行到clientSocket.ReceiveBufferSize這段程式碼就會出現錯誤,問題暫時解決,謝謝大家.

    2019年3月29日 上午 08:38
  • 你的位元組陣列並未宣告為緩衝區大小: 

    byte[] bytesFrom = new byte[10025];

    參考這篇:

    [.Net] 資料接收的常識

    宣告 緩衝Byte陣列(接收緩衝區大小)
    緩衝區內位元組數 = 物件.Read(緩衝Byte陣列, 0, 接收緩衝區大小)


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    • 已標示為解答 WilsonFan 2019年4月1日 上午 07:14
    2019年3月29日 下午 01:38
  • 在此感謝心冷熱情熄先進看出了我程式的問題也解決了我的問題,非常感謝.

    原來到了WIN 10及Windows Server 2016,TCPClient.ReceiveBufferSize增大為65536,所以我定義的陣列不夠放才出錯,之前在Windows Server 2008時TCPClient.ReceiveBufferSize為8192,所以我的程式沒有問題,不好的程式寫作習慣這次讓我吃了大虧了,要好好反省才行,謝謝,感謝.

    2019年4月1日 上午 07:20