• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            山寨:不是最好的,是最適合我們的!歡迎體驗山寨 中文版MSDN

            Blog @ Blog

            當華美的葉片落盡,生命的脈絡才歷歷可見。 -- 聶魯達

            常用鏈接

            統計

            積分與排名

            BBS

            Blog

            Web

            最新評論

            基于C#的Socket開發快速入門

            首先從原理上解釋一下采用Socket接口的網絡通訊,這里以最常用的C/S模式作為范例,首先,服務端有一個進程(或多個進程)在指定的端口等待客戶來 連接,服務程序等待客戶的連接信息,一旦連接上之后,就可以按設計的數據交換方法和格式進行數據傳輸。客戶端在需要的時刻發出向服務端的連接請求。這里為 了便于理解,提到了一些調用及其大致的功能。使用socket調用后,僅產生了一個可以使用的socket描述符,這時還不能進行通信,還要使用其他的調 用,以使得socket所指的結構中使用的信息被填寫完。

              在使用TCP協議時,一般服務端進程先使用socket調用得到一個描述 符,然后使用bind調用將一個名字與socket描述符連接起來,對于Internet域就是將Internet地址聯編到socket。之后,服務端 使用listen調用指出等待服務請求隊列的長度。然后就可以使用accept調用等待客戶端發起連接,一般是阻塞等待連接,一旦有客戶端發出連接, accept返回客戶的地址信息,并返回一個新的socket描述符,該描述符與原先的socket有相同的特性,這時服務端就可以使用這個新的 socket進行讀寫操作了。一般服務端可能在accept返回后創建一個新的進程進行與客戶的通信,父進程則再到accept調用處等待另一個連接。客 戶端進程一般先使用socket調用得到一個socket描述符,然后使用connect向指定的服務器上的指定端口發起連接,一旦連接成功返回,就說明 已經建立了與服務器的連接,這時就可以通過socket描述符進行讀寫操作了。

              .NetFrameWork為Socket通訊提供了System.Net.Socket命名空間,在這個命名空間里面有以下幾個常用的重要類分別是:

              ·Socket類 這個低層的類用于管理連接,WebRequest,TcpClient和UdpClient在內部使用這個類。

              ·NetworkStream類 這個類是從Stream派生出來的,它表示來自網絡的數據流

              ·TcpClient類 允許創建和使用TCP連接

              ·TcpListener類 允許監聽傳入的TCP連接請求

              ·UdpClient類 用于UDP客戶創建連接(UDP是另外一種TCP協議,但沒有得到廣泛的使用,主要用于本地網絡)

              下面我們來看一個基于Socket的雙機通信代碼的C#版本

              首先創建Socket對象的實例,這可以通過Socket類的構造方法來實現:

            public Socket(AddressFamily addressFamily,SocketType socketType,ProtocolType protocolType); 

              其中,addressFamily 參數指定 Socket 使用的尋址方案,socketType 參數指定 Socket 的類型,protocolType 參數指定 Socket 使用的協議。

              下面的示例語句創建一個 Socket,它可用于在基于 TCP/IP 的網絡(如 Internet)上通訊。

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

              若要使用 UDP 而不是 TCP,需要更改協議類型,如下面的示例所示:

            Socket temp = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); 

               一旦創建 Socket,在客戶端,你將可以通過Connect方法連接到指定的服務器(你可以在Connect方法前Bind端口,就是以指定的端口 發起連接,如果不事先Bind端口號的話,系統會默認在1024到5000隨機綁定一個端口號),并通過Send方法向遠程服務器發送數據,而后可以通過 Receive從服務端接收數據;而在服務器端,你需要使用Bind方法綁定所指定的接口使Socket與一個本地終結點相聯,并通過Listen方法偵 聽該接口上的請求,當偵聽到用戶端的連接時,調用Accept完成連接的操作,創建新的Socket以處理傳入的連接請求。使用完 Socket 后,使 用 Close 方法關閉 Socket。

              可以看出,以上許多方法包含EndPoint類型的參數,在Internet中, TCP/IP 使用一個網絡地址和一個服務端口號來唯一標識設備。網絡地址標識網絡上的特定設備;端口號標識要連接到的該設備上的特定服務。網絡地址和服 務端口的組合稱為終結點,在 .NET 框架中正是由 EndPoint 類表示這個終結點,它提供表示網絡資源或服務的抽象,用以標志網絡地址等信 息。.Net同時也為每個受支持的地址族定義了 EndPoint 的子代;對于 IP 地址族,該類為 IPEndPoint。IPEndPoint  類包含應用程序連接到主機上的服務所需的主機和端口信息,通過組合服務的主機IP地址和端口號,IPEndPoint 類形成到服務的連接點。

              用到IPEndPoint類的時候就不可避免地涉及到計算機IP地址,System.Net命名空間中有兩種類可以得到IP地址實例:

              ·IPAddress類:IPAddress 類包含計算機在 IP 網絡上的地址。其Parse方法可將 IP 地址字符串轉換為 IPAddress 實例。下面的語句創建一個 IPAddress 實例:

            IPAddress myIP = IPAddress.Parse("192.168.0.1"); 

               需要知道的是:Socket 類支持兩種基本模式:同步和異步。其區別在于:在同步模式中,按塊傳輸,對執行網絡操作的函數(如 Send 和  Receive)的調用一直等到所有內容傳送操作完成后才將控制返回給調用程序。在異步模式中,是按位傳輸,需要指定發送的開始和結束。同步模式是最常 用的模式,我們這里的例子也是使用同步模式。

            // 客戶端

            using System;
            using System.Collections.Generic;
            using System.Text;
            using System.IO;
            using System.Net;
            using System.Net.Sockets;

            namespace ClientDemo
            {
                
            class Program
                
            {
                    
            static void Main(string[] args)
                    
            {
                        
            try
                     
            {
                        
            int port = 2010;
                        
            string host = "127.0.0.1";
                        IPAddress ip 
            = IPAddress.Parse(host);
                        IPEndPoint ipe 
            = new IPEndPoint(ip, port);//把ip和端口轉化為IPEndPoint實例
                        Socket c = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//創建一個Socket
                        Console.WriteLine("Conneting");
                        c.Connect(ipe);
            //連接到服務器
                        string sendStr = "hello!This is a socket test";
                        
            byte[] bs = Encoding.ASCII.GetBytes(sendStr);
                        Console.WriteLine(
            "Send Message");
                        c.Send(bs, bs.Length, 
            0);//發送測試信息
                        string recvStr = "";
                        
            byte[] recvBytes = new byte[1024];
                        
            int bytes;
                        bytes 
            = c.Receive(recvBytes, recvBytes.Length, 0);//從服務器端接受返回信息
                        recvStr += Encoding.ASCII.GetString(recvBytes, 0, bytes);
                        Console.WriteLine(
            "Client Get Message:{0}", recvStr);//顯示服務器返回信息
                            c.Close();
                     }

                     
            catch (ArgumentNullException e)
                     
            {
                        Console.WriteLine(
            "ArgumentNullException: {0}", e);
                     }

                     
            catch (SocketException e)
                     
            {
                        Console.WriteLine(
            "SocketException: {0}", e);
                     }

                 Console.WriteLine(
            "Press Enter to Exit");
                    Console.ReadLine();

                  }

                }

            }

            服務端:

            using System;
            using System.Collections.Generic;
            using System.Text;
            using System.IO;
            using System.Net;
            using System.Net.Sockets;

            namespace ServerDemo
            {
                
            class Program
                
            {
                    
            static void Main(string[] args)
                    
            {
                        
            try 
                        
            {
                            
            int port = 2010;
                            
            string host = "127.0.0.1";
                            IPAddress ip 
            = IPAddress.Parse(host);
                            IPEndPoint ipe 
            = new IPEndPoint(ip, port);
                            Socket s 
            = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // 創建一個SOKCET類的實例
                            s.Bind(ipe);    // 綁定端口
                            s.Listen(0);    // 開始監聽
                            Console.WriteLine("Wait for connect");
                            Socket temp 
            = s.Accept();// 為新建連接創建新的Socket
                            Console.WriteLine("Get a Connect");
                            
            string recvStr = "";
                            
            byte[] recvBytes = new byte[1024];
                            
            int bytes;
                            bytes 
            = temp.Receive(recvBytes, recvBytes.Length, 0);   //  接收客戶端的信息
                            recvStr += Encoding.ASCII.GetString(recvBytes, 0, bytes);
                            Console.WriteLine(
            "Server Get Message:{0}", recvStr);

                            
            string sendStr = "OK! Client Send Message Successful!";
                            
            byte[] bs = Encoding.ASCII.GetBytes(sendStr);
                            temp.Send(bs, bs.Length, 
            0);
                            temp.Close();
                            s.Close();
                        }

                        
            catch (ArgumentNullException e)
                     
            {
                        Console.WriteLine(
            "ArgumentNullException: {0}", e);
                     }

                     
            catch (SocketException e)
                     
            {
                        Console.WriteLine(
            "SocketException: {0}", e);
                     }

                     Console.WriteLine(
            "Press Enter to Exit");
                     Console.ReadLine();
                    }

                }

            }


            面的例子是用的Socket類,System.Net.Socket命名空間還提供了兩個抽象高級類TCPClient和UDPClient和用于通訊流處理的NetWorkStream,讓我們看下例子

              客戶端

            TcpClient tcpClient=new TcpCLient(主機IP,端口號);
            NetworkStream ns=tcp.Client.GetStream();

              服務端

            TcpListener tcpListener=new TcpListener(監聽端口);
            tcpListener.Start();
            TcpClient tcpClient=tcpListener.AcceptTcpClient();
            NetworkStream ns=tcpClient.GetStream();

              服務端用TcpListener監聽,然后把連接的對象實例化為一個TcpClient,調用TcpClient.GetStream()方法,返回網絡流實例化為一個NetworlStream流,下面就是用流的方法進行Send,Receive

               如果是UdpClient的話,就直接UdpClient實例化,然后調用UdpClient的Send和Receive方法,需要注意的事, UdpClient沒有返回網絡流的方法,就是說沒有GetStream方法,所以無法流化,而且使用Udp通信的時候,不要服務器監聽。

              現在我們大致了解了.Net Socket通信的流程,下面我們來作一個稍微復雜點的程序,一個廣播式的C/S聊天程序。

              客戶端設計需要一個1個ListBox,用于顯示聊天內容,一個TextBox輸入你要說的話,一個Button發送留言,一個Button建立連接。

              點擊建立連接的Button后出來一個對話框,提示輸入連接服務器的IP,端口,和你的昵稱,啟動一個接受線程,負責接受從服務器傳來的信息并顯示在ListBox上面。

              服務器端2個Button,一個啟動服務,一個T掉已建立連接的客戶端,一個ListBox顯示連接上的客戶端的Ip和端口。

              比較重要的地方是字符串編碼的問題,需要先把需要傳送的字符串按照UTF8編碼,然后接受的時候再還原成為GB2312,不然中文顯示會是亂碼。

              還有一個就是接收線程,我這里簡單寫成一個While(ture)循環,不斷判斷是否有信息流入,有就接收,并顯示在ListBox上,這里有問題,在.Net2.0里面,交錯線程修改窗體空間屬性的時候會引發一個異常,不可以直接修改,需要定義一個委托來修改。

               當客戶端需要斷開連接的時候,比如點擊窗體右上角的XX,就需要定義一個this.FormClosing +=  new System.Windows.Forms.FormClosingEventHandler(this.Closing);(.Net2.0 是FormClosing系統事件),在Closing()函數里面,發送Close字符給服務端,服務器判斷循環判斷所有的連接上的客戶端傳來的信息, 如果是以Close開頭,斷開與其的連接。看到這里,讀者就會問了,如果我在聊天窗口輸入Close是不是也斷開連接呢?不是的,在聊天窗口輸入的信息傳 給服務器的時候開頭都要加上Ip信息和昵稱,所以不會沖突。 


            本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/dzfb/archive/2006/12/21/1452139.aspx

            posted on 2009-11-30 19:17 isabc 閱讀(1784) 評論(0)  編輯 收藏 引用

            廣告信息(免費廣告聯系)

            中文版MSDN:
            歡迎體驗

            亚洲精品无码久久毛片| 国产精品久久久久国产A级| 91久久精品国产免费直播| 国产精品内射久久久久欢欢| 国产成人99久久亚洲综合精品| 久久综合九色欧美综合狠狠 | 青青草国产成人久久91网| 久久久久亚洲AV无码去区首| 亚洲综合久久夜AV | 久久狠狠色狠狠色综合| 色偷偷88欧美精品久久久 | 久久精品成人免费网站| 亚洲国产成人精品无码久久久久久综合 | 蜜桃麻豆WWW久久囤产精品| 久久久亚洲欧洲日产国码aⅴ| 国产伊人久久| 久久九九有精品国产23百花影院| 无码任你躁久久久久久老妇App| 91久久成人免费| 久久精品亚洲中文字幕无码麻豆| 色偷偷91久久综合噜噜噜噜| 99久久国产综合精品五月天喷水| 久久精品国产99国产精品亚洲| 国产精品伦理久久久久久| 国产综合久久久久| 一本一道久久综合狠狠老| 蜜桃麻豆www久久国产精品| 久久er热视频在这里精品| 久久精品国产亚洲AV麻豆网站 | 97超级碰碰碰久久久久| 精品久久久久久国产| 久久久久av无码免费网| 久久婷婷色香五月综合激情 | 国产综合久久久久久鬼色| 久久亚洲私人国产精品| 色偷偷偷久久伊人大杳蕉| 中文字幕热久久久久久久| 99久久无色码中文字幕人妻| 777午夜精品久久av蜜臀| 国内精品伊人久久久影院| 久久精品国产男包|