posts - 56,  comments - 12,  trackbacks - 0
          Real time Application 實時申請技術在本文里是作為一個實例來演示在用戶(Tcpclient)申請與服務器(TcpServer)申請之間使用Socket類的情況 。該項目同樣也演示在實時項目中如何使用listview控制以及如何傳遞XML格式信息。

            TcpServer.exe 文件顯示了在單獨的thread當中(而不是在
          GUI 線程之中)TCP socket的相互通訊。

            TcpClient.exe文件同樣也使用一條單獨的線程 從Socket中讀取數據,然后對表單中的list
          view 控件進行更新。

            步聚如下:

            1.TcpServer 監聽端口8002,并且發射線程等待客戶端連結。

          Hashtable socketHolder = new Hashtable();

          Hashtable threadHolder = new Hashtable();

          public Form1()

          {

           // Required for Windows Form Designer support

           //

           InitializeComponent();

           tcpLsn = new TcpListener(8002);

           tcpLsn.Start();

           // tcpLsn.LocalEndpoint may have a bug, it only show 0.0.0.0:8002

           stpanel.Text = "Listen at: " + tcpLsn.LocalEndpoint.
          ToString ();

           Thread tcpThd = new Thread(new ThreadStart(WaitingForClient));

           threadHolder.
          Add (connectId, tcpThd);

           tcpThd.Start() ;

          }

           

           2. TcpClient與TcpSrv連接上后,發送客戶端信息數據包至TcpServer,然后發射線程,該線程是用來接收通過Socket傳來的數據。

          private void menuConn_Click(object sender, System.EventArgs e)

          {
           ConnectDlg myDlg = new ConnectDlg();

           myDlg.ShowDialog(this);

           if( myDlg.DialogResult==DialogResult.OK)

           {

            s = new Socket(AddressFamily.InterNetwork, SocketType.Stream,ProtocolType.Tcp );

            IPAddress hostadd = IPAddress.Parse(myDlg.IpAdd);

            int port=Int32.Parse(myDlg.PortNum);

            IPEndPoint EPhost = new IPEndPoint(hostadd, port);

            Try

            {

             s.Connect(EPhost);

             if (s.Connected)

             {

              Byte[] bBuf;

              string buf;

              buf = String.Format("{0}:{1}", myDlg.UserName,myDlg.PassWord);

              bBuf=ASCII.GetBytes(buf);

              s.Send(bBuf, 0 , bBuf.Length,0);

              t = new Thread(new ThreadStart(StartRecieve));

              t.Start();

              sbar.Text="Ready to recieve data";

             }

            }

            catch (Exception e1)

            {

             MessageBox.Show(e1.ToString());

            }

           }

          }

          private void StartRecieve()

          {

           miv = new MethodInvoker(this.UpdateListView);

           int cnt=0;

           string tmp=null;

           Byte[] firstb= new Byte[1];

           while (true)

           {

            try

            {

             Byte[] receive = new Byte[1];

             int ret = s.Receive(receive, 1, 0);

             if (ret > 0)

             {

              switch(receive[0])

              {

               case 11: //check start message

                 cnt=0;

                 break;

               case 10: // check end message

                 cnt=0;

                 if(firstb[0] == ':')

                  HandleCommand(tmp);

                 else if(firstb[0] == '<')

                  HandleXml(tmp);

                 else

                  HandleText(tmp);

                  tmp=null;

                  break;

                 default:

                  if (cnt == 0)

                   firstb[0] = receive[0];

                   tmp += System.Text.Encoding

                   .ASCII.GetString(receive);

                   cnt++;

                   break;

                  }

                 }

              }

              catch (Exception e)

              {

               if( !s.Connected )

                {

                 break;

                }

               }

             }

             t.Abort();

            }

           

           

           3.TcpServer接收來自TcpClient的連接請求,并且將socket 實例保存到Hash表中,然后發射線程以便控制socket的通訊,同時將客戶端信息在listview 控件中顯示出來。

          public void WaitingForClient()

          {

           while(true)

           {

            // Accept will block until someone connects

            Socket sckt = tcpLsn.AcceptSocket();

            if (connectId < 10000)

             Interlocked.Increment(ref connectId);

            Else

             connectId = 1;

             if (socketHolder.Count < MaxConnected )
           
             {

              while (socketHolder.Contains(connectId) )

              {

               Interlocked.Increment(ref connectId);

              }

             Thread td = new Thread(new ThreadStart(ReadSocket));

             lock(this)

             {

              // it is used to keep connected Sockets

              socketHolder.Add(connectId, sckt);

              // it is used to keep the active thread

              threadHolder.Add(connectId, td);

             }

             td.Start();

            }

           }

          }

          // follow function handle the communication from the clients and close the

          // socket and the thread when the socket connection is down

          public void ReadSocket()

          {

           // the connectId is keeping changed with new connection added. it can't

           // be used to keep the real connectId, the local variable realId will

           // keep the value when the thread started.

           long realId = connectId;

           int ind=-1;

           Socket s = (Socket)socketHolder[realId];

           while (true)

           {

            if(s.Connected)

            {

             Byte[] receive = new Byte[37] ;

             Try

             {

              // Receive will block until data coming

              // ret is 0 or Exception happen when Socket connection

              // is broken

              int ret=s.Receive(receive,receive.Length,0);

              if (ret > 0)

              {

               string tmp = null;

               tmp=System.Text.Encoding.ASCII.GetString(receive);

               if(tmp.Length > 0)

               {

                DateTime now1=DateTime.Now;

                String strDate;

                strDate = now1.ToShortDateString() + " " + now1.ToLongTimeString();

                ListViewItem newItem = new ListViewItem();

                string[] strArry=tmp.Split(':');

                int code = checkUserInfo(strArry[0]);

                if(code==2)

                {

                 userHolder.Add(realId, strArry[0]);

                 newItem.SubItems.Add(strArry[0]);

                 newItem.ImageIndex = 0;

                 newItem.SubItems.Add(strDate);

                 this.listView2.Items.Add(newItem);

                 ind=this.listView2.Items.IndexOf(newItem);

                }

                else if( code==1)

               }

             }

             else

             {

              this.listView2.Items[ind].ImageIndex=1;

              keepUser=false;

              break;

             }

            }

            catch (Exception e)

            {

             if( !s.Connected )

             {

              this.listView2.Items[ind].ImageIndex=1;

              keepUser=false;

              break;

             }

            }

           }

           }
           
           CloseTheThread(realId);

          }

          private void CloseTheThread(long realId)

          {

           socketHolder.Remove(realId);

           if(!keepUser) userHolder.Remove(realId);

            lock(this)

            {

             Thread thd = (Thread)threadHolder[realId];

             threadHolder.Remove(realId);

            }

            thd.Abort();

           }

           

           

          4. 點擊Load Data菜單,從文件中載入信息,然后把所有信息傳送到每個將與TcpServer相連接的客戶端,客戶端會自己更新它的listview。不管是 TcpServer 還是 TcpClient ,它們都從運作中的線程之中獲取數據,再在主線程中更新Listview control。下面則講述的是通過MethodInvoker實現該功能。

          public void LoadThread()

          {

          MethodInvoker mi = new MethodInvoker(this.UpdateListView);

          string tmp = null;

          StreamReader sr = File.OpenText("Issue.txt");

          while((tmp = sr.ReadLine()) !=null )

          {

          if (tmp =="")

          break;



          isu.symbol= Mid(tmp, 0, 4);

          isu.bid = Mid(tmp, 4, 5);

          isu.offer = Mid(tmp, 9, 5);

          isu.volume = Mid(tmp, 16, tmp.Length-16);



          sendMsg ="\v" + tmp + "\n"; //add send message's head and end char

          SendDataToAllClient(tmp);

          this.BeginInvoke(mi);



          JobDone.WaitOne();

          }

          sr.Close();

          fThd.Abort();

          }

          private void SendDataToAllClient(string str)

          {

          foreach (Socket s in socketHolder.Values)

          {

          if(s.Connected)

          {

          Byte[] byteDateLine=ASCII.GetBytes(str.ToCharArray());

          s.Send(byteDateLine, byteDateLine.Length, 0);

          }

          }

          }

            以下代碼 操縱XML文件,并且為客戶端生成XML文件。

          public void LoadXmlThread()

          {

          MethodInvoker miv = new MethodInvoker(this.UpdateListView);

          string tmp = null;

          string xmlString = null;



          int recordFlg = -1;

          int textCount =0;

          xmlString = "\v"+"";



          XmlTextReader tr = new XmlTextReader("issue.xml");

          while(tr.Read())

          {

          switch (tr.NodeType)

          {

          case XmlNodeType.Element:

          if (tr.Name == "Issue")

          {

          recordFlg++;

          if(recordFlg > 0)

          {

          textCount=0;

          xmlString += CreateXmlElement(

          tr.Name, 2);

          xmlString += "\n";

          SendDataToAllClient(xmlString);

          xmlString = "\v"+"
          version='1.0'?>";



          this.BeginInvoke(miv);

          JobDone.WaitOne();

          }

          }

          if (recordFlg >= 0)

          {

          xmlString += CreateXmlElement(

          tr.Name, 1);

          tmp = tr.Name;

          }



          break;

          case XmlNodeType.Text:

          switch(++textCount)

          {

          case 1:

          isu.symbol=tr.Value;

          break;

          case 2:

          isu.bid=tr.Value;

          break;

          case 3:

          isu.offer=tr.Value;

          break;

          case 4:

          isu.volume=tr.Value;

          break;

          }

          xmlString += tr.Value;

          xmlString += CreateXmlElement(tmp, 2);

          break;

          }

          }

          fThd.Abort();

          }

          string CreateXmlElement(string elem, int ord)

          {

          string tmp = null;

          if (ord == 1)

          tmp = String.Format("<{0}>", elem);

          else

          tmp = String.Format("", elem);



          return tmp;

          }


          以下功能演示的是如何設置TcpClient中Listview控件的 BackColor和 Forecolor屬性 。
          private void UpdateListView()

          {

          int ind=-1;

          for (int i=0; i < this.listView1.Items.Count;i++)

          {

          if (this.listView1.Items[i].Text == isu.symbol.ToString())

          {

          ind=i;

          break;

          }

          }

          if (ind == -1)

          {

          ListViewItem newItem new ListViewItem(isu.symbol.ToString());

          newItem.SubItems.Add(isu.bid);

          newItem.SubItems.Add(isu.offer);

          newItem.SubItems.Add(isu.volume);



          this.listView1.Items.Add(newItem);

          int i=this.listView1.Items.IndexOf(newItem);

          setRowColor(i, System.Drawing.Color.FromA#ffffaf);

          setColColorHL(i, 0, System.Drawing.Color.FromA#800000);

          setColColorHL(i, 1, System.Drawing.Color.FromA#800000);

          this.listView1.Update();

          Thread.Sleep(300);

          setColColor(i, 0, System.Drawing.Color.FromA#ffffaf);

          setColColor(i, 1, System.Drawing.Color.FromA#ffffaf);

          }

          else

          {

          this.listView1.Items[ind].Text = isu.symbol.ToString();

          this.listView1.Items[ind].SubItems[1].Text = (isu.bid);

          this.listView1.Items[ind].SubItems[2].Text = (isu.offer);

          this.listView1.Items[ind].SubItems[3].Text = (isu.volume);

          setColColorHL(ind, 0, System.Drawing.Color.FromA#800000);

          setColColorHL(ind, 1, System.Drawing.Color.FromA#800000);

          this.listView1.Update();

          Thread.Sleep(300);

          setColColor(ind, 0, System.Drawing.Color.FromA#ffffaf);

          setColColor(ind, 1, System.Drawing.Color.FromA#ffffaf);

          }

          JobDone.Set();

          }



          private void setRowColor(int rowNum, Color colr )

          {

          for (int i=0; i < this.listView1.Items[rowNum].SubItems.Count;i++)

          if (rowNum%2 !=0)

          this.listView1.Items[rowNum].SubItems[i].BackColor = colr;

          }



          private void setColColor(int rowNum, int colNum, Color colr )

          {

          if (rowNum%2 !=0)

          this.listView1.Items[rowNum].SubItems[colNum].BackColor=colr;

          else

          this.listView1.Items[rowNum].SubItems[colNum].BackColor =

          System.Drawing.Color.FromA#f8f8f8;

          if (colNum==0)

          {

          this.listView1.Items[rowNum].SubItems[colNum].ForeColor =

          System.Drawing.Color.FromA#800040;

          this.listView1.Items[rowNum].SubItems[colNum].BackColor =

          System.Drawing.Color.FromA#c5c5b6;

          }

          else

          this.listView1.Items[rowNum].SubItems[colNum].ForeColor =

          System.Drawing.Color.FromA#141414;

          }



          private void setColColorHL(int rowNum, int colNum, Color colr )

          {

          this.listView1.Items[rowNum].SubItems[colNum].BackColor = colr;

          this.listView1.Items[rowNum].SubItems[colNum].ForeColor =

          System.Drawing.Color.FromA#ffffff;

          }

            運行該例子的步驟

            1. 在A機上運行TcpServer.exe文件。

            2. 在A機或B機上運行一次或多次TcpClient.exe文件。

            3. 在TcpClient端,點擊菜單連接,進入TcpServer正在運行中的服務器端。在編輯欄鍵入用戶名及口令,點擊確認。

            4. 當在TcpServer頂部的istview上瞧見客戶端的提示時,則在TcpServer,上點擊Load Data菜單,然后實時數據則會出現在TcpServer 和TcpClien上。

            注意:請確認Data file, Issue.txt and Issue.xml等文件總是處于同一根目錄下,正如TcpSvr.exe 和 MaskedTextBox.dll, WTcpClient.exe.是處于同一目錄下一樣。

            Update at 10/20/2001.

            當添加/刪除項目時,請鎖住Hash表,這樣可以確保線程的安全。

            添加功能,以便生成和處理XML格式文件。

            在發送訊息至客戶端時,請在服務器端添加發送訊息起始和結尾的字符。

            上述方法可以增加客戶端的穩定性。


          苦笑枯 2007-01-19 00:13 發表評論

          文章來源:http://www.aygfsteel.com/kuxiaoku/articles/94803.html
          posted on 2007-01-19 00:13 苦笑枯 閱讀(225) 評論(0)  編輯  收藏 所屬分類: C#
          收藏來自互聯網,僅供學習。若有侵權,請與我聯系!

          <2007年1月>
          31123456
          78910111213
          14151617181920
          21222324252627
          28293031123
          45678910

          常用鏈接

          留言簿(2)

          隨筆分類(56)

          隨筆檔案(56)

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 泰和县| 左贡县| 余姚市| 霍山县| 鲜城| 榕江县| 裕民县| 古田县| 青神县| 六安市| 武乡县| 年辖:市辖区| 张家川| 山丹县| 蛟河市| 栖霞市| 松潘县| 南川市| 台东县| 盐山县| 赤峰市| 济阳县| 南靖县| 新沂市| 徐州市| 洮南市| 张掖市| 来凤县| 诏安县| 密云县| 武山县| 崇州市| 葫芦岛市| 玉溪市| 虹口区| 什邡市| 玛纳斯县| 灌云县| 当雄县| 桓仁| 黄冈市|