.NET网络编程学习(二)
System.Net.Sockets有很多類,其中最重要的就是Socket類.
?
Socket類
public class Socket : IDisposable
Socket 類為網絡通信提供了一套豐富的方法和屬性。Socket 類允許您使用 ProtocolType 枚舉中所列出的任何一種協議執行異步和同步數據傳輸。
?
public Socket(AddressFamily addressFamily,SocketType socketType,ProtocolType protocolType);
其中,addressFamily 參數指定Socket使用的尋址方案,比如AddressFamily.InterNetwork表明為IP版本4的地址;socketType參數指定 Socket的類型,比如SocketType.Stream表明連接是基于流套接字的,而SocketType.Dgram表示連接是基于數據報套接字的。protocolType參數指定Socket使用的協議,比如ProtocolType.Tcp表明連接協議是運用TCP協議的,而 Protocol.Udp則表明連接協議是運用UDP協議的。
?
Socket 類對異步方法遵循 .NET Framework 命名模式。例如,同步的 Receive 方法對應于異步的 BeginReceive 和 EndReceive 方法。
(1)如果當前使用的是面向連接的協議(如 TCP),則服務器可以使用 Listen 方法偵聽連接。Accept 方法處理任何傳入的連接請求,并返回可用于與遠程主機進行數據通信的 Socket。可以使用此返回的 Socket 來調用 Send 或 Receive 方法。如果要指定本地 IP 地址和端口號,請在調用 Listen 方法之前先調用 Bind 方法。如果您希望基礎服務提供程序為您分配可用端口,請使用端口號 0。如果希望連接到偵聽主機,請調用 Connect 方法。若要進行數據通信,請調用 Send 或 Receive 方法。
(2)如果當前使用的是無連接協議(如 UDP),則根本不需要偵聽連接。調用 ReceiveFrom 方法可接受任何傳入的數據報。使用 SendTo 方法可將數據報發送到遠程主機。
?
同步模式的Socket編程的基本過程如下:
(1)創建一個Socket實例對象。
(2)將上述實例對象連接到一個具體的終結點(EndPoint)。
(3)連接完畢,就可以和服務器進行通訊:接收并發送信息。
(4)通訊完畢,用ShutDown()方法來禁用Socket。
(5)最后用Close()方法來關閉Socket。
?
對于基于Tcp的Socket,涉及到服務器端的偵聽(Listen)和客戶端的連接(Connect)
以下通過一個簡單的Http服務器程序來看看服務器端的程序設計:
(1)BaseConnection是個封裝Socket表示一個連接的類.
Codepublic?class?BaseConnection
{
????????Socket?sock;
????????public?BaseConnection(Socket?sock)
????????{
????????????this.sock?=?sock;
????????}
????????//把客戶端請求文件中的字符替換掉
????????string?ProcessString(string?input)
????????{
????????????StringBuilder?result?=?new?StringBuilder();
????????????for?(int?i?=?0;?i?<?input.Length;?i++)
????????????{
????????????????if?(input[i]?==?'/')
????????????????{
????????????????????result.Append('\\');
????????????????}
????????????????else
????????????????{
????????????????????result.Append(input[i]);
????????????????}
????????????}
????????????return?result.ToString();
????????}
????????///?<summary>
????????///?讀取請求信息,返回客戶端請求的文件名
????????///?</summary>
????????///?<returns></returns>
????????public?string?getRequest()??
????????{
????????????string?s?=?null?;
????????????byte[]?buff?=?new?byte[1024];
????????????int?recCount?=?0;
????????????try
????????????{
????????????????//從socket讀取請求信息
????????????????recCount?=?sock.Receive(buff,?buff.Length,?SocketFlags.None);
????????????????s?=?ASCIIEncoding.ASCII.GetString(buff,?0,?recCount);
????????????????Console.WriteLine("請求的詳細信息是:"?+?s);
????????????????if?(s.IndexOf("GET")?>?-1)
????????????????{
????????????????????s?=?s.Substring(5);
????????????????????int?fend?=?s.IndexOf("?");
????????????????????s?=?s.Substring(0,?fend);?//取得請求文件的路徑及文件名
????????????????}
????????????????return?ProcessString(s);
????????????}
????????????catch?(Exception?e)
????????????{
????????????????Console.WriteLine(e.Message);
????????????}
????????????return?"";
????????}
????????///?<summary>
????????///?返回客戶端請求的文件
????????///?</summary>
????????///?<param?name="fname"></param>
????????public?void?sendResponse(string?fname)?
????????{
????????????byte[]?buff?=?new?byte[1024];
????????????string?filePath?=?@"C:\Inetpub\wwwroot\"?+?fname;
????????????int?count?=?0;
????????????if?(filePath.IndexOf("..")?>?-1)?//使訪問的文件限制在目錄C:\Inetpub\wwwroot\下
????????????{
????????????????Console.WriteLine("沒有權限訪問!");
????????????????return;
????????????}
????????????Console.WriteLine("look?for?"?+?filePath);
????????????if?(File.Exists(filePath))?//檢查文件是否存在
????????????{
????????????????using?(BinaryReader?fs?=?new?BinaryReader(File.Open(filePath,?FileMode.Open)))
????????????????{
????????????????????while?((count?=?fs.Read(buff,?0,?1024))?>?0)
????????????????????{
????????????????????????sock.Send(buff,?count,?SocketFlags.None);//發送信息
????????????????????}
????????????????}
????????????}
????????????else
????????????{
????????????????throw?new?FileNotFoundException("文件:"?+?filePath?+?"不存在!");
????????????}
????????}
????????public?void?ConClose()??//關閉socket
????????{
????????????sock.Shutdown(SocketShutdown.Both);
????????????sock.Close();
????????}
}
(2)Main方法
?
Code????????static?void?Main(string[]?args)
????????{
????????????Socket?ssock?=?new?Socket(AddressFamily.InterNetwork,?SocketType.Stream,ProtocolType.Tcp);
????????????IPAddress?hostIp?=?Dns.GetHostEntry("localhost").AddressList[0];
????????????IPEndPoint?ep?=?new?IPEndPoint(hostIp,?80);
????????????ssock.Bind(ep);?//綁定
????????????Console.WriteLine("開始偵聽.");
????????????//開始偵聽
????????????ssock.Listen(32);
????????????while?(true)
????????????{
????????????????Socket?sock?=?ssock.Accept();?//等待客戶端請求
????????????????Console.WriteLine("有一個客戶端請求");
????????????????BaseConnection?client?=?new?BaseConnection(sock);
????????????????try
????????????????{
????????????????????string?file?=?client.getRequest();
????????????????????Console.WriteLine("客戶端請求的文件是:"?+?file);
????????????????????client.sendResponse(file);
????????????????}
????????????????catch?(Exception?e)
????????????????{
????????????????????Console.WriteLine(e.Message);
????????????????}
????????????????finally
????????????????{
????????????????????client.ConClose();?//關閉連接
????????????????}
????????????????Console.WriteLine("結束一個請求");
????????????????Console.WriteLine("");
????????????}
????????}
?
(3)測試假設在你C:\Inetpub\wwwroot目錄下有一個info.html
啟動服務器端:
打開瀏覽器輸入:http://localhost/info.html
?結果如下:
同時服務器端輸出:
雖然很簡單,但我們卻的確寫了一個http服務器程序.
?
主要參考資料:MSDN
總結
以上是生活随笔為你收集整理的.NET网络编程学习(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vc配置文件的生成
- 下一篇: WPF ListBox(ListView