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

首頁 > 學院 > 開發設計 > 正文

.net網絡編程之一:Socket編程

2019-11-17 04:03:33
字體:
來源:轉載
供稿:網友
在.net下進行網絡編程其實也相對比較簡單,因為在.net類庫已經提供了大量封裝好的類。在.net下網絡編程比較底層的類是System.Net.Sockets.Socket類,這個類提供了豐富的方法和屬性,并且還提供了異步數據傳輸支持。
對Socket類做一個簡單的介紹,它有如下常見方法:
public Socket Accept ():為新建連接創建新的 Socket。    
public void Bind (EndPoint localEP):使 Socket 與一個本地終結點相關聯。  
public void Close ():關閉 Socket 連接并釋放所有關聯的資源。注意這個方法有沖載方法。
public void Connect (EndPoint remoteEP):建立與遠程主機的連接。注意這個方法有重載方法。
public void Disconnect (bool reuseSocket):關閉套接字連接并是否允許重用套接字。  
public void Listen (int backlog):將 Socket 置于偵聽狀態。  
public int Receive (byte[] buffer):接收來自綁定的 Socket 的數據。注意這個方法有重載方法。
public int ReceiveFrom (byte[] buffer,ref EndPoint remoteEP):接收數據報并存儲源終結點。注意這個方法有重載方法。
public int Send (byte[] buffer):將數據發送到連接的 Socket。注意這個方法有重載方法。
public void SendFile (string fileName):將文件和可選數據異步發送到連接的 Socket。注意這個方法有重載方法。
public int SendTo (byte[] buffer,EndPoint remoteEP):將數據發送到特定終結點。注意這個方法有重載方法。
public void Shutdown (SocketShutdown how):禁用某 Socket 上的發送和接收。
說明:
因為在網絡傳輸時傳輸的數據都是二進制形式的(表現為字節數組),所以如果要傳輸類似于中文這樣的雙字節字符就需要在傳輸之前用合適的編碼轉換成字節數組,然后接收方按照發送方的編碼將接收到字節數組轉換成字符串。另外,注意接收數據的時候是先聲明了一個字節數組,然后將接收到的數據保存到字節數組中,這個方法有個返回值表示實際接收了多少字節數據。這是因為數組是不可變的,假如聲明了一個1024字節大小的數組,而發送方僅發送1字節數據,而接收方并不直到發送方發送的數據量把整個1024字節當作發送發送的數據的話,最終會發生錯誤。
要實現一個服務器端的面向連接的Socket用于接收客戶端的請求的話,有如下步驟:
(1)首先根據ip地址和端口號實例化一個Socket,注意端口要要大于1024并且不要使用特殊端口號,要大于1024的原因是1024以下的端口號已經被指派了,而1433、3306這樣的端口號已經被用作SQL Server和MySQL的默認端口號了,若指定為這些端口號容易發生沖突。
(3)接著調用Bind()方法進行綁定,然后再調用Listen()方法用于監聽,Listen()方法的參數用于指定監聽的隊列大小,也就是最多可容納的等待接受的傳入連接數。
(4)再調用Accept()方法,調用這個方法之后會是程序處于阻塞狀態,直至有客戶端連接為止。當有客戶端連接,這個方法將會返回一個新的Socket,使用這個Socket與客戶端進行通訊。
(5)使用Accept()方法返回的新Socket的Send()方法就可以向客戶端發送數據了,還可以使用這個新Socket的Receive()接收客戶端的數據。
(6)最后終止與客戶端會話時,注意使用ShutDown()方法關閉Socket連接,并且使用Close()方法釋放所占用的資源。

使用Socket類編寫客戶端的Socket程序步驟如下:
(1)首先指定遠程主機和端口號實例化Socket類,注意連接的端口號一定要與服務器監聽的端口號一致。
(2)接著調用Connect()方法連接遠程主機。
(3)連接到遠程主機之后就可以調用Send()方法向服務器發送請求了,然后可以調用Receive()方法接收服務器響應數據,注意如果是發送的類似于中文這樣的雙字節字符串的話,還需要按照服務器響應的字符串編碼將字節數組轉換成字符串。
最后終止與客戶端會話時,注意使用ShutDown()方法關閉Socket連接,并且使用Close()方法釋放所占用的資源。
需要特別說明的是上面是建立連接式Socket(如建立TCP協議Socket)的一般步驟,如果是建立非連接式Socket(如UDP協議Socket)就不需要進行監聽端口了,直接使用ReceiveFrom()方法就能接收來自指定主機端口的數據,用SendTo()方法就能向直接主機端口發送數據。
下面一個例子來演示Socket的編程,在這個例子里服務器端可以處理多個客戶端請求并響應,具體的做法是每接收到一個客戶端請求就新建一個線程來與客戶端通訊,主程序依然繼續監聽,在例子中新建的與客戶端通訊的Socket類僅處理客戶端的日期時間請求(為了演示,這里做了簡化),根據客戶端的請求的不同發送日期時間中響應信息到客戶端,客戶端接收到數據之后在控制臺顯示。
服務器端主要由兩個類組成:ServerSocket類和SocketThread類,ServerSocket類用于監聽客戶端連接請求,SocketThread類用于接收日期時間顯示請求并做出應答。
ServerSocket類代碼如下(ServerSocket類和SocketThread類位于同一個類庫項目中):

view plaincopy to clipboardPRint?
using System;   
using System.Net;   
using System.Net.Sockets;   
using System.Text;   
  
namespace ServerSocket   
{   
    /// <summary>   
    /// Socket監聽服務器,用于監聽客戶端連接請求   
    /// 作者:周公   
    /// 編寫時間:2009-03-18       
    /// </summary>   
    public class ServerSocket:IDisposable   
    {   
        Socket listener = null;   
        /// <summary>   
        /// 開始監聽指定端口   
        /// </summary>   
        public void StartListening(int port)   
        {   
            // Data buffer for incoming data.   
            byte[] bytes = new Byte[1024];   
  
            //以運行服務器端程序所在的機器為服務器監聽客戶端連接   
            IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());   
            IPAddress ipAddress = ipHostInfo.AddressList[0];   
            IPEndPoint localEndPoint = new IPEndPoint(ipAddress, port);   
  
            //創建一個TCP/IP Socket用于監聽客戶端連接   
            Socket listener = new Socket(AddressFamily.InterNetwork,   
                SocketType.Stream, ProtocolType.Tcp);   
  
            try  
            {   
                //先綁定要監聽的主機和端口   
                listener.Bind(localEndPoint);   
                //再開始監聽,并且指定監聽隊列的最大長度   
                listener.Listen(10);   
  
                //開始監聽連接   
                while (true)   
                {   
                    Console.WriteLine("等待客戶端連接...");   
                    //線程將一直阻塞直到有新的客戶端連接   
                    Socket handler = listener.Accept();   
                    //啟用一個新的線程用于處理客戶端連接   
                    //這樣主線程還可以繼續接受客戶端連接   
                    SocketThread socketThread = new SocketThread(handler);   
                }   
  
            }   
            catch (Exception e)   
            {   
                Console.WriteLine(e.ToString());   
            }   
  
        }   
  
        public static int Main(String[] args)   
        {   
            ServerSocket server = new ServerSocket();   
            server.StartListening(11000);   
            return 0;   
        }  

        #region IDisposable 成員   
  
        public void Dispose()   
        {   
            if (listener != null)   
            {   
                listener.Shutdown(SocketShutdown.Both);   
                listener.Close();   
            }   
        }  

        #endregion   
    }   
}   
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace ServerSocket
{
    /// <summary>
    /// Socket監聽服務器,用于監聽客戶端連接請求
    /// 作者:周公
    /// 編寫時間:2009-03-18    
    /// </summary>
    public class ServerSocket:IDisposable
    {
        Socket listener = null;
        /// <summary>
        /// 開始監聽指定端口
        /// </summary>
        public void StartListening(int port)
        {
            // Data buffer for incoming data.
            byte[] bytes = new Byte[1024];

            //以運行服務器端程序所在的機器為服務器監聽客戶端連接
            IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
            IPAddress ipAddress = ipHostInfo.AddressList[0];
            IPEndPoint localEndPoint = new IPEndPoint(ipAddress, port);

            //創建一個TCP/IP Socket用于監聽客戶端連接
            Socket listener = new Socket(AddressFamily.InterNetwork,
                SocketType.Stream, ProtocolType.Tcp);

            try
            {
                //先綁定要監聽的主機和端口
                listener.Bind(localEndPoint);
                //再開始監聽,并且指定監聽隊列的最大長度
                listener.Listen(10);

                //開始監聽連接
                while (true)
                {
                    Console.WriteLine("等待客戶端連接...");
                    //線程將一直阻塞直到有新的客戶端連接
                    Socket handler = listener.Accept();
                    //啟用一個新的線程用于處理客戶端連接
                    //這樣主線程還可以繼續接受客戶端連接
                    SocketThread socketThread = new SocketThread(handler);
                }

            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }

        }

        public static int Main(String[] args)
        {
            ServerSocket server = new ServerSocket();
            server.StartListening(11000);
            return 0;
        }

        #region IDisposable 成員

        public void Dispose()
        {
            if (listener != null)
            {
                listener.Shutdown(SocketShutdown.Both);
                listener.Close();
            }
        }

        #endregion
    }
}  

SocketThread類代碼如下:

view plaincopy to clipboardprint?
using System;   
using System.Collections.Generic;   
using System.Text;   
using System.Threading;   
using System.Net.Sockets;   
  
namespace ServerSocket   
{   
    /// <summary>   
    /// 用于處理客戶端請求的Socket   
    /// 作者:周公   
    /// 編寫時間:2009-03-18   
    /// </summary>   
    public class SocketThread:IDisposable   
    {   
        private Socket socket;   
        private Thread thread;   
        private bool isListening = false;   
        private string text;   
        /// <summary>   
        /// 構造方法   
        /// </summary>   
        /// <param name="socket">用于處理客戶端應答的Socket</param>   
        public SocketThread(Socket socket)   
        {   
            this.socket = socket;   
            isListening = true;   
            thread = new Thread(new ThreadStart(Work));   
            thread.Start();   
        }   
  
  
        public void Work()   
        {   
            byte[] buffer=new byte[1024];   
            while (isListening)   
            {   
                int receivedLength = socket.Receive(buffer);   
                text=System.Text.Encoding.UTF8.GetString(buffer,0,receivedLength);   
                //<EOF>是自定義的協議,表示中止消息交流   
                if (text.IndexOf("<EOF>") > -1)   
                {   
                    isListening=false;   
                    socket.Send(new byte[] { 0 });   
                }   
                else  
                {   
                    //Console.WriteLine("接收到的數據:" + text);   
                    //根據客戶端的請求獲取相應的響應信息   
                    string message = GetMessage(text);   
                    //將響應信息以字節的方式發送到客戶端   
                    socket.Send(Encoding.UTF8.GetBytes(message));   
                }   
            }   
        }   
        private string GetMessage(string request)   
        {   
            string message = string.Empty;   
            //Console.WriteLine("Message=" + request);   
            switch (request)   
            {   
                case "date": message = "服務器日期:"+DateTime.Now.ToString("yyyy-MM-dd"); break;   
                case "time": message ="服務器時間:"+ DateTime.Now.ToString("HH:mm:ss"); break;   
                case "datetime": message = "服務器日期時間:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); break;   
                case "year": message = "服務器年份:" + DateTime.Now.Year.ToString(); break;   
                case "month": message = "服務器月份:" + DateTime.Now.Month.ToString(); break;   
                case "day": message = "這是本月第" + DateTime.Now.Day.ToString()+"天"; break;   
                default: message = "不正確的參數"; break;   
            }   
            return message;   
        }  

        #region IDisposable 成員   
  
        public void Dispose()   
        {   
            isListening = false;   
            if (thread != null)   
            {   
                if (thread.ThreadState != ThreadState.Aborted)   
                {   
                    thread.Abort();   
                }   
                thread = null;   
            }   
            if (socket != null)   
            {   
                socket.Shutdown(SocketShutdown.Both);   
                socket.Close();   
            }   
        }  

        #endregion   
  
           
    }   
}  
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Net.Sockets;

namespace ServerSocket
{
    /// <summary>
    /// 用于處理客戶端請求的Socket
    /// 作者:周公
    /// 編寫時間:2009-03-18
    /// </summary>
    public class SocketThread:IDisposable
    {
        private Socket socket;
        private Thread thread;
        private bool isListening = false;
        private string text;
        /// <summary>
        /// 構造方法
        /// </summary>
        /// <param name="socket">用于處理客戶端應答的Socket</param>
        public SocketThread(Socket socket)
        {
            this.socket = socket;
            isListening = true;
            thread = new Thread(new ThreadStart(Work));
            thread.Start();
        }


        public void Work()
        {
            byte[] buffer=new byte[1024];
            while (isListening)
            {
                int receivedLength = socket.Receive(buffer);
                text=System.Text.Encoding.UTF8.GetString(buffer,0,receivedLength);
                //<EOF>是自定義的協議,表示中止消息交流
                if (text.IndexOf("<EOF>") > -1)
                {
                    isListening=false;
                    socket.Send(new byte[] { 0 });
                }
                else
                {
                    //Console.WriteLine("接收到的數據:" + text);
                    //根據客戶端的請求獲取相應的響應信息
                    string message = GetMessage(text);
                    //將響應信息以字節的方式發送到客戶端
                    socket.Send(Encoding.UTF8.GetBytes(message));
                }
            }
        }
        private string GetMessage(string request)
        {
            string message = string.Empty;
            //Console.WriteLine("Message=" + request);
            switch (request)
            {
                case "date": message = "服務器日期:"+DateTime.Now.ToString("yyyy-MM-dd"); break;
                case "time": message ="服務器時間:"+ DateTime.Now.ToString("HH:mm:ss"); break;
                case "datetime": message = "服務器日期時間:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); break;
                case "year": message = "服務器年份:" + DateTime.Now.Year.ToString(); break;
                case "month": message = "服務器月份:" + DateTime.Now.Month.ToString(); break;
                case "day": message = "這是本月第" + DateTime.Now.Day.ToString()+"天"; break;
                default: message = "不正確的參數"; break;
            }
            return message;
        }

        #region IDisposable 成員

        public void Dispose()
        {
            isListening = false;
            if (thread != null)
            {
                if (thread.ThreadState != ThreadState.Aborted)
                {
                    thread.Abort();
                }
                thread = null;
            }
            if (socket != null)
            {
                socket.Shutdown(SocketShutdown.Both);
                socket.Close();
            }
        }

        #endregion

        
    }
}

客戶端請求的Socket代碼如下(與前面兩個類位于不同的控制臺項目中):

view plaincopy to clipboardprint?
using System;   
using System.Net;   
using System.Net.Sockets;   
using System.Text;   
  
namespace ServerSocket   
{   
    /// <summary>   
    /// 客戶端請求的Socket包裝類   
    /// 作者:周公   
    /// 編寫時間:2009-03-18   
    /// </summary>   
    public class ClientSocket:IDisposable   
    {   
        private Socket sender = null;   
        private bool isListening = false;   
        //定義用于接收服務器響應的存儲區.   
        private byte[] bytes = new byte[1024];   
        //用于終止Soket的消息   
        private string shutDownMessage = "<EOF>";   
  
        public ClientSocket()   
        {   
            try  
            {   
                //設置要連接的主機信息并使用11000作為監聽端口.   
                IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());   
                IPAddress ipAddress = ipHostInfo.AddressList[0];   
                IPEndPoint remoteEP = new IPEndPoint(ipAddress, 11000);   
  
                // 創建一個TCP/IP協議的socket連接   
                sender = new Socket(AddressFamily.InterNetwork,   
                    SocketType.Stream, ProtocolType.Tcp);   
                sender.Connect(remoteEP);   
                isListening = true;   
            }   
            catch (Exception ex)   
            {   
                   
                Console.WriteLine(ex.ToString());   
            }   
        }   
  
        public void StartClient()   
        {   
            // 連接到遠程主機,并捕獲所有信息   
            try  
            {   
                   
                Console.WriteLine("連接到主機{0}",   
                    sender.RemoteEndPoint.ToString());   
                OutParameters();   
                string consoleMessage = Console.ReadLine();   
                while (isListening&&!string.IsNullOrEmpty(consoleMessage))   
                {   
                    consoleMessage = consoleMessage.ToLower();   
                    if (consoleMessage == "bye")   
                    {   
                        SendShutDownMessage();   
                    }   
                    else  
                    {   
                        string resultMessage=SendMessage(consoleMessage);   
                        Console.WriteLine(resultMessage);   
                        OutParameters();   
                        consoleMessage = Console.ReadLine();   
                        //Console.WriteLine("consoleMessage=" + consoleMessage);   
                    }   
                }   
  
            }   
            catch (ArgumentNullException ane)   
            {   
                Console.WriteLine("參數異常 : {0}", ane.ToString());   
            }   
            catch (SocketException se)   
            {   
                Console.WriteLine("出現Socket異常: {0}", se.ToString());   
            }   
            catch (Exception e)   
            {   
                Console.WriteLine("出現了異常 : {0}", e.ToString());   
            }   
  
        }   
        /// <summary>   
        /// 向遠程主機發送信息   
        /// </summary>   
        /// <param name="message">要發送的信息</param>   
        public string SendMessage(string message)   
        {   
            byte[] buffer = Encoding.UTF8.GetBytes(message);   
            sender.Send(buffer);   
            int count=sender.Receive(bytes);   
            return Encoding.UTF8.GetString(bytes, 0, count);   
        }   
        /// <summary>   
        /// 向服務器發送關閉Socket信息,并中止與服務器的連接   
        /// </summary>   
        public void SendShutDownMessage()   
        {   
            SendMessage(shutDownMessage);   
            Console.WriteLine("已經關閉與服務器的連接");   
            isListening = false;   
            Environment.Exit(0);   
        }   
  
        private void OutParameters()   
        {   
            Console.WriteLine("參數說明:");   
            Console.WriteLine("獲取服務器日期:date");   
            Console.WriteLine("獲取服務器時間:time");   
            Console.WriteLine("獲取服務器日期時間:datetime");   
            Console.WriteLine("獲取服務器年份:year");   
            Console.WriteLine("獲取服務器月份:month");   
            Console.WriteLine("獲取服務器天數:day");   
            Console.WriteLine("關閉連接:bye");   
            Console.WriteLine("請輸入你要進行的操作:");   
        }   
  
        public static int Main(String[] args)   
        {   
            ClientSocket client = new ClientSocket();   
            client.StartClient();   
            return 0;   
        }  

        #region IDisposable 成員   
  
        public void Dispose()   
        {   
            isListening = false;   
            if (sender != null)   
            {   
                sender.Shutdown(SocketShutdown.Both);   
                sender.Close();   
            }   
        }  

        #endregion   
    }   
}  
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace ServerSocket
{
    /// <summary>
    /// 客戶端請求的Socket包裝類
    /// 作者:周公
    /// 編寫時間:2009-03-18
    /// </summary>
    public class ClientSocket:IDisposable
    {
        private Socket sender = null;
        private bool isListening = false;
        //定義用于接收服務器響應的存儲區.
        private byte[] bytes = new byte[1024];
        //用于終止Soket的消息
        private string shutDownMessage = "<EOF>";

        public ClientSocket()
        {
            try
            {
                //設置要連接的主機信息并使用11000作為監聽端口.
                IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
                IPAddress ipAddress = ipHostInfo.AddressList[0];
                IPEndPoint remoteEP = new IPEndPoint(ipAddress, 11000);

                // 創建一個TCP/IP協議的socket連接
                sender = new Socket(AddressFamily.InterNetwork,
                    SocketType.Stream, ProtocolType.Tcp);
                sender.Connect(remoteEP);
                isListening = true;
            }
            catch (Exception ex)
            {
                
                Console.WriteLine(ex.ToString());
            }
        }

        public void StartClient()
        {
            // 連接到遠程主機,并捕獲所有信息
            try
            {
                
                Console.WriteLine("連接到主機{0}",
                    sender.RemoteEndPoint.ToString());
                OutParameters();
                string consoleMessage = Console.ReadLine();
                while (isListening&&!string.IsNullOrEmpty(consoleMessage))
                {
                    consoleMessage = consoleMessage.ToLower();
                    if (consoleMessage == "bye")
                    {
                        SendShutDownMessage();
                    }
                    else
                    {
                        string resultMessage=SendMessage(consoleMessage);
                        Console.WriteLine(resultMessage);
                        OutParameters();
                        consoleMessage = Console.ReadLine();
                        //Console.WriteLine("consoleMessage=" + consoleMessage);
                    }
                }

            }
            catch (ArgumentNullException ane)
            {
                Console.WriteLine("參數異常 : {0}", ane.ToString());
            }
            catch (SocketException se)
            {
                Console.WriteLine("出現Socket異常: {0}", se.ToString());
            }
            catch (Exception e)
            {
                Console.WriteLine("出現了異常 : {0}", e.ToString());
            }

        }
        /// <summary>
        /// 向遠程主機發送信息
        /// </summary>
        /// <param name="message">要發送的信息</param>
        public string SendMessage(string message)
        {
            byte[] buffer = Encoding.UTF8.GetBytes(message);
            sender.Send(buffer);
            int count=sender.Receive(bytes);
            return Encoding.UTF8.GetString(bytes, 0, count);
        }
        /// <summary>
        /// 向服務器發送關閉Socket信息,并中止與服務器的連接
        /// </summary>
        public void SendShutDownMessage()
        {
            SendMessage(shutDownMessage);
            Console.WriteLine("已經關閉與服務器的連接");
            isListening = false;
            Environment.Exit(0);
        }

        private void OutParameters()
        {
            Console.WriteLine("參數說明:");
            Console.WriteLine("獲取服務器日期:date");
            Console.WriteLine("獲取服務器時間:time");
            Console.WriteLine("獲取服務器日期時間:datetime");
            Console.WriteLine("獲取服務器年份:year");
            Console.WriteLine("獲取服務器月份:month");
            Console.WriteLine("獲取服務器天數:day");
            Console.WriteLine("關閉連接:bye");
            Console.WriteLine("請輸入你要進行的操作:");
        }

        public static int Main(String[] args)
        {
            ClientSocket client = new ClientSocket();
            client.StartClient();
            return 0;
        }

        #region IDisposable 成員

        public void Dispose()
        {
            isListening = false;
            if (sender != null)
            {
                sender.Shutdown(SocketShutdown.Both);
                sender.Close();
            }
        }

        #endregion
    }
}

上面的三個類位于兩個控制臺項目中ServerSocket類和SocketThread類位于同一個類庫項目中,其中ClientSocket類位于另一個控制臺項目中,編譯之后會生成兩個exe文件,運行的時候首先運行服務器端exe程序以便監聽,再運行客戶端exe程序。這個程序運行的效果如下:

上面的三個類位于兩個控制臺項目中ServerSocket類和SocketThread類位于同一個類庫項目中,其中ClientSocket類位于另一個控制臺項目中,編譯之后會生成兩個exe文件,運行的時候首先運行服務器端exe程序以便監聽,再運行客戶端exe程序。這個程序運行的效果如下


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 宝丰县| 万年县| 宝丰县| 安新县| 余干县| 什邡市| 烟台市| 哈密市| 临武县| 北碚区| 邢台县| 九江市| 新干县| 黎城县| 通榆县| 巴彦淖尔市| 手游| 英超| 泸水县| 荔浦县| 舞钢市| 葫芦岛市| 高阳县| 德昌县| 宜兴市| 崇左市| 泰顺县| 凤山市| 顺昌县| 高密市| 吴忠市| 遵化市| 黑龙江省| 木兰县| 搜索| 张家界市| 武宁县| 眉山市| 新绛县| 邮箱| 芦溪县|