国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C# > 正文

基于UDP、TCP協(xié)議的C#網(wǎng)絡(luò)編程

2023-05-12 12:29:37
字體:
供稿:網(wǎng)友

與UDP不同,基于TCP協(xié)議的編程的服務(wù)器端有一個監(jiān)聽對象:TcpListener,它負(fù)責(zé)監(jiān)聽來自客戶端的消息并處理,并且必須在保持連接的情況下與客戶端保持互動,下面舉個例子來說明這個問題。

 示例一:基于TCP協(xié)議的網(wǎng)絡(luò)編程

窗體:

  Form2做為本程序的服務(wù)器端,當(dāng)按下Start后,啟動服務(wù),剩下的是一個Form1,我啟動了兩次,都連接到Form2,當(dāng)在Form1的Send欄里寫入小寫字母并按下Send按鈕后,將該字符串發(fā)送至Form2,同時Form2將該字符串轉(zhuǎn)換為大寫,返回給發(fā)送者,說明完畢,出個謎語,誰知道兩個Form1里字母是啥意思?

       Form2:(服務(wù)器端)

public partial class Form2 : Form
    {

        //聲明監(jiān)聽對象
        private TcpListener tl;

        //聲明網(wǎng)絡(luò)流
        private NetworkStream ns;
        public Form1()
        {
            CheckForIllegalCrossThreadCalls = false;
            InitializeComponent();           
        }

        private void btnStart_Click(object sender, EventArgs e)
        {

            //開啟8888端口的監(jiān)聽
            tl = new TcpListener(8888);
            tl.Start();

            //開啟線程
            Thread th = new Thread(new ThreadStart(listen));
            th.IsBackground = true;
            th.Start();
        }
        private void listen()
                 
            while (true)
             

                //獲得響應(yīng)的Socket
                Socket sock = tl.AcceptSocket();  

                //通過該Socket實例化網(wǎng)絡(luò)流           
                ns = new NetworkStream(sock);

                //ClientTcp是添加的類,下面會做說明
                ClientTcp ct = new ClientTcp(ns);

                //ct_MyEvent方法注冊ClientTcp類的MyEvent事件
                ct.MyEvent += new MyDelegate(ct_MyEvent);

                //開啟線程
                Thread th = new Thread(new ThreadStart(ct.TcpThread));
                th.IsBackground = true;
                th.Start();
            }
        }

        void ct_MyEvent(string temp)
        {

            //設(shè)置服務(wù)器端TextBox的值
            this.textBox1.Text = temp;
        }
    }

 

       Form1:(客戶端)

 

public partial class Form1 : Form
    {

        //聲明Tcp客戶端
        private TcpClient tc;

        //聲明網(wǎng)絡(luò)流
        private NetworkStream ns;
        public Form1()
        {
            CheckForIllegalCrossThreadCalls = false;
            InitializeComponent();
        }

        private void button2_Click(object sender, EventArgs e)
        {

            //注冊本機8888端口
            tc = new TcpClient("localhost",8888);

            //實例化網(wǎng)絡(luò)流對象
            ns = tc.GetStream();
            string temp = this.textBox1.Text;

            StreamWriter sw = new StreamWriter(ns);
            StreamReader sr = new StreamReader(ns);

            //將TextBox1的值傳給服務(wù)器端
            sw.WriteLine(temp);
            sw.Flush();

            //接收服務(wù)器端回傳的字符串
            string str = sr.ReadLine();
            this.textBox2.Text = str;
            sr.Close();
            sw.Close();
        }
    }

 

       ClientTcp類:

    //聲明一個需要一個字符串參數(shù)的委托

    public delegate void MyDelegate(string temp);
    class ClientTcp
    {

        //設(shè)置網(wǎng)絡(luò)流局部對象
        private NetworkStream ns;

        //聲明類型為MyDelegate的事件MyEvent
        public event MyDelegate MyEvent;

        //構(gòu)造函數(shù)中接收參數(shù)以初始化
        public ClientTcp(NetworkStream ns)
        {
            this.ns = ns;
        }

        //服務(wù)器端線程所調(diào)用的方法
        public void TcpThread()
        {

            //獲得相關(guān)的封裝流
            StreamReader sr = new StreamReader(ns);
            string temp = sr.ReadLine();

            //接收到客戶端消息后觸發(fā)事件將消息回傳
            MyEvent(temp);
            StreamWriter sw = new StreamWriter(ns);

            //轉(zhuǎn)換為大寫后發(fā)送消息給客戶端
            sw.WriteLine(temp.ToUpper());
            sw.Flush();
            sw.Close();
            sr.Close();
        }
    }

這里說下為什么需要ClientTcp這么個類,說這個之前,先說一下為什么服務(wù)器端需要開啟一個新的線程來監(jiān)控端口,這個原因比較簡單,Socket sock = tl.AcceptSocket();  這個方法會造成阻塞,也就是說如果沒有得到客戶端的響應(yīng),TcpListenr將一直監(jiān)聽下去,這就會造成程序的假死,因此我們需要單獨開一個線程來監(jiān)聽我們的8888端口,我們觀察服務(wù)器端(Form2)可以看出,NetworkStream是一個全局變量(實際上局部與全局都是一樣),如果CPU忙的過來,直接把ClientTcp里的方法拿到Form2里寫沒問題,但是一旦客戶端過多造成數(shù)據(jù)擁擠,那很可能當(dāng)運算還未結(jié)束,NetworkStream就已經(jīng)換人了,因此當(dāng)我們?nèi)〉媚晨蛻舳藢?yīng)的NetworkStream后,應(yīng)該考慮立刻將它封裝到一個類中,再在該類中再對該NetworkStream做相應(yīng)的操作,ClientTcp這個類就是為這個設(shè)計的,而當(dāng)封裝了NetworkStream后,我們發(fā)現(xiàn)從客戶端傳過來的值是我們需要的,因此就用到了事件的回調(diào),這個我前面有篇文章里講過了,見http://blog.sina.com.cn/u/4c459776010008ws,基于TCP協(xié)議的網(wǎng)絡(luò)編程基礎(chǔ)的東西就這些,寫法很固定,但是需要很多的技巧,前幾天試著寫一個聊天室程序,差點沒吐血,果然不是一般的麻煩。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 奉新县| 林周县| 福建省| 天峻县| 买车| 永仁县| 隆昌县| 客服| 泾源县| 嵊州市| 郑州市| 沙湾县| 资阳市| 房山区| 视频| 老河口市| 松潘县| 潍坊市| 望城县| 新巴尔虎右旗| 江西省| 九龙县| 怀宁县| 金溪县| 宜宾县| 隆化县| 海门市| 甘南县| 南皮县| 图木舒克市| 华阴市| 睢宁县| 黎城县| 军事| 宕昌县| 定远县| 达日县| 开封市| 陇川县| 阿坝| 吉林市|