C#套接字工作速度非常慢

时间:2016-04-18 15:52:42

标签: c# sockets

 string strMessage = Encoding.UTF8.GetString(message);
                    MessageBox.Show("Message: " + strMessage);
                    int numToRemove = Int32.Parse(strMessage);
                    char head = strMessage[0];
                    if(head.ToString() == "2")
                    {
                        MessageBox.Show("test");
                    }  

此代码正常,但如果我添加

button5.text = "X";

然后,它开始工作的速度非常慢,而#34; X"在显示的按钮上,以及if语句之后的任何内容都不起作用。

这是整个代码:

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace TCPSockets {
    public partial class Form1 : Form {
        /************
         * Spremenljivke
         * 
         * 
         * **********/
        // odjemalec/strežnik
        TcpClient client = null;
        TcpListener listener = null;
        IPAddress ip = null;
        int port = 1337;

        // niti
        Thread thClient = null;
        Thread thListener = null;

        // podatkovni tok
        NetworkStream dataStream = null;
        string sporocilo = "";
        int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9};


        public Form1() {
            InitializeComponent();
        }

        /*************
         * Strežnik (listener)
         * 
         * ***********/
        private void button1_Click(object sender, EventArgs e) {
            // IP & port
            ip = IPAddress.Parse(textBox1.Text);
            port = Convert.ToInt32(textBox2.Text);

            // nit => sicer vmesnik blokira, ko kličemo AcceptTcpClient()
            thListener = new Thread(new ThreadStart(ListenForConnections));
            thListener.IsBackground = true;
            thListener.Start();
        }

        // ListenForConnections posluša na vratih in sprejema nove odjemalce
        // Ko odjemalca sprejme, obdela njegovo sporočilo
        private void ListenForConnections() {
            listener = new TcpListener(ip, port);
            listener.Start();

            // neskončna zanka, če želimo prejemati več sporočil
            // neskončna zanka zato, ker ne moremo vedeti koliko sporočil bomo prejeli
            while (true) {
                try {
                    client = listener.AcceptTcpClient();    // ta funkcija blokira nit dokler se odjemalec ne poveže (ne pošlje sporočila)

                    // pridobivanje sporočila iz podatkovnega toka
                    dataStream = client.GetStream();    // dobimo podatkovni tok odjemalca in beremo podatke iz njega

                    byte[] message = new byte[1024];
                    dataStream.Read(message, 0, message.Length);
                    dataStream.Close();

                    string strMessage = Encoding.UTF8.GetString(message);
                    MessageBox.Show("Strežnik: Dobil sem sporočilo: " + strMessage);
                    int numToRemove = Int32.Parse(strMessage);
                    char head = strMessage[0];
                    if(head.ToString() == "2")
                    {
                        button4.Text = "X";

                    }  
                    /*  else if(head.ToString() == "2")
                      {
                          button5.Text = "X";
                          sporocilo = "";
                      }
                    */


                }
                // obdelovanje izjem => ko ustavljamo strežnik prožimo izjemo
                catch (Exception ex) {
                    thListener.Join();  // enostavno zaključimo nit z .Join() in ne .Abort()!!!
                }
            }
        }

        // ustavljanje strežnika
        private void button3_Click(object sender, EventArgs e) {
            if (client != null && client.Connected) client.Close(); // če imamo povezanega odjemalca, ta klic proži izjemo v while(true)...
            listener.Stop(); // če nimamo povezanega odjemalca, ta klic proži izjemo v while(true)...
        }

        /**********
         * Odjemalec (client)
         * 
         * ********/

        private void button2_Click(object sender, EventArgs e) {
            ip = IPAddress.Parse(textBox1.Text);
            port = Convert.ToInt32(textBox2.Text);

            // ustvarimo novo povezavo na strežnik v ločeni niti
            // kot parameter si pošljemo TcpClient objekt, da celotno povezavo izvedemo v drugi niti
            // na tak način bi lahko izvedli več simultanih povezav na isti strežnik (recimo za pošiljanje več datotek hkrati, ali pa tudi za izvedbo DDoS napada)
            client = new TcpClient();
            thClient = new Thread(new ParameterizedThreadStart(SendPacket));
            thClient.IsBackground = true;
            thClient.Start(client);
        }

        // nit za pošiljanje sporočila

        private void button4_Click(object sender, EventArgs e)
        {

            sporocilo = "1";
        }

        private void SendPacket(object pClient)
        {
            string message = sporocilo;

            // spet try-catch blok, da polovimo napake (recimo strežnik offline)
            try
            {
                client = (TcpClient)pClient; // samo type cast parametra
                client.Connect(ip, port);    // dejanska povezava s strežnikom

                dataStream = client.GetStream(); // pridobivanje podatkovnega toka in pisanje vanj
                byte[] strMessage = Encoding.UTF8.GetBytes(message);
                dataStream.Write(strMessage, 0, strMessage.Length);
                dataStream.Close(); // vedno, VEDNO!!! zapiramo podatkovne toke...
                client.Close();     // ...kot tudi zapremo povezavo, ko smo končali
            }
            // če je bila napaka, jo lahko na uporabniku prijazen način obdelamo
            catch (Exception ex)
            {
                MessageBox.Show("Odjemalec: Pošiljanje ni bilo uspešno!");
            }

        }

        private void button5_Click(object sender, EventArgs e)
        {
            sporocilo = "2";
        }
    }
}

1 个答案:

答案 0 :(得分:0)

除了我可以对你的编码风格做的几十点(特别是你应该用英文编写代码)之外,你的主要问题是你试图从另一个线程更新GUI对象。我觉得有趣的是你没有看到异常,但你必须去GUI(主)线程来更新GUI对象。
请参阅this answer,了解您应该如何操作。