簡體   English   中英

C#TcpClient無法發送或讀取100%的數據?

[英]C# TcpClient not sending or reading 100% of data?

大家好。 我正在編寫一個簡單的客戶端/服務器應用程序(就經驗而言,聯網對我來說還很新),客戶端在其中發送服務器數據,然后服務器將其輸出到文本框。 一切正常,除了一個小細節...似乎有時建立了連接,但是沒有發送或讀取數據(無法計算出哪個),因此文本框中未輸出任何內容。 每次建立連接時,計數器都會增加,接收數據塊時也是如此。 當您將兩者進行比較時,連接數是正確的,但數據計數器通常較低,有時多達一半。 無論如何,如果有人可以給我一些建議或指出正確的方向,將不勝感激!

如果需要的話,下面是代碼:

(SERVER_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;
using System.Net.Sockets;
using System.Threading;

namespace Server
{
    public partial class Form1 : Form
    {
        public int Connections = 0;
        public int blocks = 0;
        public int threads = 0;
        public Thread MasterThread;
        public TcpListener Master;
        public volatile bool Run;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        public void StartMaster()
        {
            Master = new TcpListener(IPAddress.Any, 1986);
            Master.Start();
            MasterThread = new Thread(new ThreadStart(RunMaster));
            MasterThread.Start();
        }

        public void RunMaster()
        {
            threads++;
            label6.Text = String.Format("{0}", threads);

            while (Run)
            {
                TcpClient client = Master.AcceptTcpClient();
                Connections++;
                label4.Text = String.Format("{0}", Connections);
                Thread ClientThread = new Thread(new ParameterizedThreadStart(RunClient));
                ClientThread.Start(client);
            }

            Master.Stop();

            threads--;
            label6.Text = String.Format("{0}", threads);
        }

        public void RunClient(object tcpClient)
        {
            TcpClient client = (TcpClient)tcpClient;
            byte[] buffer = new byte[4096];
            int byteCount = 0;
            NetworkStream stream = client.GetStream();
            threads++;
            label6.Text = String.Format("{0}", threads);

            while (Run)
            {
                try
                {
                    byteCount = stream.Read(buffer, 0, 4096);
                }
                catch
                {
                    //Connections--;
                    break;
                }

                if (byteCount == 0)
                {
                    //Connections--;
                    break;
                }

                blocks++;
                label5.Text = String.Format("{0}", blocks);

                textBox1.AppendText(Encoding.ASCII.GetString(buffer, 0, byteCount) + "\r\n");
            }

            client.Close();

            threads--;
            label6.Text = String.Format("{0}", threads);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Run = true;
            StartMaster();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            Run = false;
        }
    }
}

(CLIENT_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;
using System.Net.Sockets;
using System.Threading;

namespace Client
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1986);
            TcpClient client = new TcpClient();
            try
            {
                client.Connect(endPoint);
            }
            catch
            {
                MessageBox.Show("Connect Error");
            }

            NetworkStream stream = client.GetStream();
            byte[] data = Encoding.ASCII.GetBytes(textBox1.Text);
            stream.Write(data, 0, data.Length);
            stream.Flush();
            client.Close();
        }
    }
}

謝謝,
特里斯坦!

好吧,首先,您要破壞自己的診斷程序:

catch
{
    //Connections--;
    break;
}

為什么在沒有任何日志記錄的情況下吞下異常? 可能會引發異常,您無法知道。 理想情況下你應該捕獲特定的異常,而當捕捉異常至少登錄是怎么回事。

另一方面, Wireshark應該幫助您確定是否正在發送數據。

我還沒有徹底了解您的代碼,但是快速瀏覽后,您可以在沒有適當鎖定的情況下從多個線程訪問變量。 x++;這樣的語句x++; 必須讀取x的值,對其進行遞增並寫回。 現在,如果有兩個線程執行此操作,則可能會遇到這種情況:

x = 0

Thread 1           Thread 2
------------------------
Read (0)
                   Read (0)
Increment (1)
                   Increment (1)
Write (1)
                   Write (1)

=> x = 1 instead of 2

如果您需要從多個線程訪問變量,請始終進行同步,除非您確切地知道自己在做什么。 例如,創建並使用如下所示的同步對象:

int threads = 0;
object threadSync = new object();

...

lock (threadSync) {
    threads++;
}

然后一次只能有一個線程訪問該變量,並且值會正確遞增。

編輯:另一個問題是您從與創建控件不同的線程訪問可見控件。 早期的.NET版本允許這樣做,但較新的版本不允許。 如果需要更新狀態消息,則需要查看控件的InvokeRequired屬性,如果將其設置為true,請使用Control.Invoke(...)調用設置該屬性的方法。

暫無
暫無

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

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