【.NET】網絡編程總結


1、首先說下計算機網絡中的TCP/IP參考模型

  TCP/IP把網絡分為5層,每一層負責完成不同的功能

    1)應用層:傳輸報文,提供各種網絡應用,有FTP、SMTP、HTTP等協議

    2)運輸層:傳輸報文段,為應用程序的客戶機和服務器之間提供傳輸應用層報文服務,協議有TCP,UDP

    3)網絡層:傳輸數據包,協議有IP協議,選路協議

    4)鏈路層:傳輸數據幀,以太網就屬於這個層

    5)物理層:在節點之間傳輸比特流

  應用程序是通過套接字訪問網絡下層的服務的,套接字是網絡運輸層和應用層的一個編程接口,在程序中通過套接字來進行TCP和UDP傳輸,運輸層以下的層對程序員透明

TCP和UDP是最基本的傳輸協議,應用層的所有協議都是基於這兩個協議進行封裝擴展的

  TCP:可靠的,面向連接的連接數據傳輸服務,傳輸的是字節流,能保證數據的有序性

    1)建立連接(三次握手)  2)傳輸數據  3)斷開連接(四次握手)

  UDP:不可靠,面向數據報的無連接的數據傳輸服務,傳輸的是是數據包,不保證數據的有序性

    廣播:可以向同一個子網內的所有主機發送廣播數據

    組播:可以向所有加入組網的主機發送組播數據

2、編程(本節由於篇幅太長,這里只說TCP)

  .NET 框架提供了下面幾個類對實現網絡通信:

    Socket:提供最基本的TCP和UDP服務

    TcpListener/TcpClient 和 UdpClient:對Socket類進行了基本封裝

    NetworkStream:網絡流,對網絡數據的寫入和讀取

  使用套接字的步驟

    TCP:服務器:創建套接字 -》 綁定套接字Bind -》 監聽套接字Listen -》 接受連接Accept -》 發送/接受Send/Receive -》 關閉套接字CLose

      :客戶端:創建套接字 -》                     連接 -》      發送/接受Send/Receive -》 關閉套接字CLose

    UDP:創建套接字 -》 綁定套接字Bind -》  發送/接受SendTo/ReceiveFrom -》 關閉套接字CLose

  1)Socket(使用異步方式連接和收發信息,因為等待連接和等待數據的時候會讓主線程阻塞)

     這里就不貼代碼了,跟下面的差不多,后面下載的代碼有(我用的VS2012,低版本不能查看可以直接看源文件的代碼)

  2)TcpListener/TcpClient(這里也使用異步方式來連接和接收信息)

    首先創建一個異步用的數據對象

        public class StateObject
        {
            public NetworkStream networkstream = null;
            public byte[] buffer = new byte[1024];
            public StateObject(NetworkStream netstream)
            {
                this.networkstream = netstream;
            }
        }

    1)服務器端(異步監聽,當收到連接,則異步讀取數據,注意捕獲連接斷開時的異常)

 

        TcpListener listener;
        NetworkStream networkstream;

        private void btnBind_Click(object sender, EventArgs e)
        {
            //綁定,啟動異步接受連接
            try
            {
                int port = int.Parse(tbPort.Text);
                IPAddress ipaddress = IPAddress.Parse(tbIP.Text);
                IPEndPoint endpoint = new IPEndPoint(ipaddress, port);
                
                listener = new TcpListener(endpoint);
                listener.Start(10);        //監聽數位10
                //開始異步接收連接請求
                listener.BeginAcceptTcpClient(DoAcceptTcpClientCallback, listener);
                btn.Text = "Close";
            }
            catch (ArgumentNullException) { }
            catch (SocketException) { }
        }
        //異步接收請求函數
        public void DoAcceptTcpClientCallback(IAsyncResult ar)
        {
            TcpListener listener = (TcpListener)ar.AsyncState;
            try
            {
                TcpClient client = listener.EndAcceptTcpClient(ar);
                //收到連接
                this.BeginInvoke(new ThreadStart(() =>
                {
                    //收到連接請求,這里可以讓主線程更新UI
                }));
                networkstream = new NetworkStream(client.Client);
                StateObject so = new StateObject(networkstream);
                
                //開始異步讀取數據
                networkstream.BeginRead(so.buffer, 0, so.buffer.Length, ReadCallback, so);

                //如果需要繼續監聽,則繼續異步接收
                listener.BeginAcceptTcpClient(DoAcceptTcpClientCallback, listener);
            }
            catch (ObjectDisposedException)
            {
                //Socket關閉
            }
        }
        //異步讀取數據函數
        public void ReadCallback(IAsyncResult ar)
        {
            StateObject so = (StateObject)ar.AsyncState;
            try
            {
                NetworkStream myNetworkStream = so.networkstream;
                int length = myNetworkStream.EndRead(ar);
                string receivemsg = Encoding.UTF8.GetString(so.buffer, 0, length);
                this.BeginInvoke(new ThreadStart(() =>
                {
                    //收到數據,在這里可以讓主線程更新UI
                }));
                so.buffer = new byte[1024];
                //繼續接收數據
                myNetworkStream.BeginRead(so.buffer, 0, so.buffer.Length, ReadCallback, so);
            }
            catch (IOException)
            {
                this.BeginInvoke(new ThreadStart(() =>
                {
                    //連接斷開
                }));
                networkstream = null;
            }
        }

 

    這樣,服務器端就完成了監聽

  2)客戶端(同樣通過異步實現)

        TcpClient client;
        NetworkStream networkstream;
        private void btnConnect_Click(object sender, EventArgs e)
        {
            int port = int.Parse(tbPort.Text);
            IPAddress ipaddress = IPAddress.Parse(tbIP.Text);
            IPEndPoint endpoint = new IPEndPoint(ipaddress, port);

            if (client == null)
            {
                //開始異步連接
                client = new TcpClient();
                client.BeginConnect(ipaddress, port, ConnectCallback, client);
            }
        }
        private void ConnectCallback(IAsyncResult ar)
        {

            TcpClient t = ar.AsyncState as TcpClient;
            try
            {
                t.EndConnect(ar);
                networkstream = t.GetStream();
                this.BeginInvoke(new ThreadStart(() =>
                {      
                    //連接成功                
                }));
                //開始異步接受數據
                StateObject so = new StateObject(networkstream);
                networkstream.BeginRead(so.buffer, 0, so.buffer.Length, ReadCallback, so);
            }
            catch (SocketException)
            { 
                this.BeginInvoke(new ThreadStart(() => 
                {
                    //連接失敗,讓UI更新
                }));
            }
        }
        public void ReadCallback(IAsyncResult ar)
        {
            StateObject so = (StateObject)ar.AsyncState;
            try
            {
                NetworkStream myNetworkStream = so.networkstream;
                int length = myNetworkStream.EndRead(ar);
                string receivemsg = Encoding.UTF8.GetString(so.buffer, 0, length);
                this.BeginInvoke(new ThreadStart(() =>
                {
                    //更新UI
                }));
                //繼續異步接受數據
                so.buffer = new byte[1024];
                myNetworkStream.BeginRead(so.buffer, 0, so.buffer.Length, ReadCallback, so);
            }
            catch (IOException)
            {
                this.BeginInvoke(new ThreadStart(() =>
                {
                    //連接斷開
                }));
                networkstream = null;
            }
        }

  3)接下來是發送數據

        private void btnSend_Click(object sender, EventArgs e)
        {
            if (networkstream != null)
            {
                byte[] sendbyte = System.Text.Encoding.UTF8.GetBytes("你好:)");
                networkstream.Write(sendbyte, 0, sendbyte.Length);
            }
            else
            {
                tbMsg.AppendText("未連接\n");
            }
        }

  具體項目代碼  http://files.cnblogs.com/bomo/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B.zip

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM