1. 程式人生 > >C# 實現C/S程式的開發

C# 實現C/S程式的開發


using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net.Sockets;
using System.Net;
namespace Customer
{
    public partial class CustomerForm : Form
    {
        public CustomerForm()
        {
            InitializeComponent();
        }
        IPHostEntry host;//本機的IP
        TcpListener TCL;//建立一個監聽
        Socket skt;//  用於傳送命令和接受資料的
        IPEndPoint IP;//拼接IP和埠
        private void Form1_Load(object sender, EventArgs e)
        {//窗體載入後自動連線段客戶端
            try
            {
                host = Dns.Resolve(Dns.GetHostName());//獲取本機 的IP
                 IP = new IPEndPoint(host.AddressList[0], 10086);//將IP和埠拼接起來
                this.Text += "(" + IP.ToString() + ")";//在程式的標題上面顯示本機的IP
                TCL = new TcpListener(IP);//初始化一個偵聽,偵聽埠為10086
                TCL.Start();//啟動偵聽
               BeginAcceptClient();//非同步接受連線請求
               txtResults.Text += "/r/n /t伺服器已經正常啟動....偵聽埠:" + IP.Port.ToString();//顯示在訊息框上面
               TxtSelect();//這是控制顯示框的滾動條
            }
            catch (Exception ex)
            {
                txtResults.Text+="/r/n /t連線肉雞出錯!詳細:"+ex.Message;
                TxtSelect();//這也是控制滾動條的
                skt.Close();//出現異常就關閉連線
            }
        }

//-----------------------非同步接收傳入的連線--------------------------------
        public static ManualResetEvent tcpManualResetEvent = new ManualResetEvent(true);

        public void BeginAcceptClient()
        {//非同步接受客戶端的請求
            tcpManualResetEvent.Set();//設定當前的執行緒處於等待狀態...允許一個或者多個執行緒等待
            TCL.BeginAcceptSocket(new AsyncCallback(AcceptClient),TCL);//接受客戶端的請求
            tcpManualResetEvent.WaitOne();//直到連線這個執行緒完成為止
           
        }
   
       public  string Results = "";//轉換後的訊息
       int count;//接收的資料長度
       public void AcceptClient(IAsyncResult ar)
       {//非同步接受傳入的連線請求
           Control.CheckForIllegalCrossThreadCalls = false;//這是讓當前的控制元件能在通過執行緒訪問
           TcpListener Listener = (TcpListener)ar.AsyncState;//非同步的狀態
           skt = Listener.EndAcceptSocket(ar);//接受傳入的請求
          
           if (skt.Connected)//判斷是否已經有客戶端連線上,如果連線上後就讀取資料
           {
            
               BeginAcceptClient();//再次接受客戶端連線的請求,這個能解決客戶端斷開連線後能再次連線上
             
               txtResults.Text += "/r/n /t提示:有機子上線了..";
               TxtSelect();
               //接收資料
               try
               {
                   byte[] bt = new byte[1024 * 1024];//宣告一個Byte陣列來存放接受到的資料
                   count = skt.Receive(bt);//將接受到的資料放到數組裡面
                   if (count > 0)//判斷是否有資料,如果有就將讀去到的資料訊息顯示到訊息框上.
                   {

                       Thread T = new Thread(new ThreadStart(AcceptDate), 80);//使用一個執行緒來將訊息顯示到文字框
                       T.Start();//啟動執行緒 並將接收資料 然後現在在文字框上。
                       txtResults.Text="/r/n小雞說1:"+Encoding.BigEndianUnicode.GetString(bt);//將Byte型別轉成字串顯示到文字框上....
                       TxtSelect();//控制文字框上的滾動條的方法
                   }
                 
               }
               catch (Exception ex)
               {
                   skt.Close();//出現異常就關閉連線
                   txtResults.Text += "/r/n /t提示:接收資料出錯!";
                   TxtSelect();//控制文字框的滾動條
               }
           }
           tcpManualResetEvent.WaitOne();
        }
       public void AcceptDate()
       { //接收資料,這是接受資料的方法

           if (skt.Connected && count>0)//如果有客戶端連線上了就讀去資料
           {
               try
               {
                   byte[] bt = new byte[1024*1024];//同樣也是宣告一個數組來存放資料
                   skt.Receive(bt);//此方法是將接收的資料儲存到數組裡面
                   Results = Encoding.BigEndianUnicode.GetString(bt);//將資料轉成String型別然後顯示到訊息框上...
                   for (int i = 0; i < bt.Length; i++)
                   {//將Byte陣列清理
                       bt[i] = btRecylcer;//接收完資料後就清理陣列的資料
                   }
                   txtResults.Text += "/r/n小雞說:" + Results;
                   TxtSelect();
                   if (count>0)
                   {
                       Thread T = new Thread(new ThreadStart(AcceptDate2), 50);//啟動一個執行緒將接收到的資料顯示到文字框上
                       T.Start();

                   }
               }
               catch (Exception ex)
               {

                   txtResults.Text += "/r/n /t接收資料出錯:" + ex.Message;
                   TxtSelect();
               }
           }
       }

       public void AcceptDate2()
       { //再次接受資料
           //txtResults.Text += "/r/n /t小雞說3:" + Results;
           AcceptDate();//接收資料的方法
      
       }


       byte btRecylcer = new byte();
        private void btnPerForm_Click(object sender, EventArgs e)
        {//傳送按扭
            try
            {
                byte[] bt = new byte[1024 * 1024];//宣告一個數組存放要傳送的的資料
                bt = Encoding.BigEndianUnicode.GetBytes(txtDOS.Text);//將需要傳送的訊息轉換成Byte型別的資料
                skt.Send(bt);//將訊息或者命令傳送到客戶端
                txtResults.Text += "/r/n /t你傳送:" + Encoding.BigEndianUnicode.GetString(bt) + "/r/n";
                TxtSelect();//控制文字框的滾動條
                txtDOS.Clear();//傳送完後清理文字框
                for (int i = 0; i < bt.Length; i++)
                {//清理陣列
                    bt[i] = btRecylcer;
                }
            }
            catch (Exception ex)
            {
                txtResults.Text += "/r/n /t傳送命令出錯:" + ex.Message ;
                TxtSelect();
            }
        }

        private void TxtSelect()
        {//這是控制訊息框的滾動條讓滾動條一直都是望下拉
            txtResults.Select(txtResults.Text.Length + 100, txtResults.Text.Length);
            txtResults.ScrollToCaret();
        }

    }
}