亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C#中異步Socket通信編程代碼實例

 更新時間:2015年03月27日 12:03:30   投稿:junjie  
這篇文章主要介紹了C#中異步Socket通信編程代碼實例,本文講解了什么是Socket編程的異步是實現(xiàn)、如何實現(xiàn)Socket異步通信并給出了代碼實例,需要的朋友可以參考下

本文將在C#中Socket同步通信的基礎上,分析和研究Socket異步編程的實現(xiàn)方法,目的是深入了解Socket編程的基本原理,增強對網(wǎng)絡游戲開發(fā)相關內(nèi)容的認識。

什么是Socket編程的異步是實現(xiàn)

所謂Socket編程的異步實現(xiàn)是指按照異步過程來實現(xiàn)Socket編程,那么什么是異步過程呢,我們把在完成了一次調(diào)用后通過狀態(tài)、通知和回調(diào)來告知調(diào)用者的方式成為異步過程,換句話說,在異步過程中當調(diào)用一個方法時,調(diào)用者并不能夠立刻得到結果,只有當這個方法調(diào)用完畢后調(diào)用者才能獲得調(diào)用結果。這樣做的好處是什么呢?答案是高效。相信大家還記得我們在《C#中Socket通信編程的同步實現(xiàn)》這篇文章中使用多線程來實現(xiàn)簡單聊天的案例吧,在這個案例中我們需要開啟兩個線程來不斷監(jiān)聽客戶端的連接和客戶端的消息,這樣的效率肯定是很低的。那么現(xiàn)在好了,我們可以通過異步過程來解決這個問題,下面我們就來看看如何實現(xiàn)Socket的異步通信。

如何實現(xiàn)Socket異步通信

服務端

基本流程

1.創(chuàng)建套接字
2.綁定套接字的IP和端口號——Bind()
3.使套接字處于監(jiān)聽狀態(tài)等待客戶端的連接請求——Listen()
4.當請求到來后,使用BeginAccept()和EndAccept()方法接受請求,返回新的套接字
5.使用BeginSend()/EndSend和BeginReceive()/EndReceive()兩組方法與客戶端進行收發(fā)通信
6.返回,再次等待新的連接請求
7.關閉套接字

代碼示例

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

namespace AsyncServer
{
  public class AsyncTCPServer
  {
    public void Start()
    {
      //創(chuàng)建套接字
      IPEndPoint ipe = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6065);
      Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
      //綁定端口和IP
      socket.Bind(ipe);
      //設置監(jiān)聽
      socket.Listen(10);
      //連接客戶端
      AsyncAccept(socket);
    }

    /// <summary>
    /// 連接到客戶端
    /// </summary>
    /// <param name="socket"></param>
    private void AsyncAccept(Socket socket)
    {
      socket.BeginAccept(asyncResult =>
      {
        //獲取客戶端套接字
        Socket client = socket.EndAccept(asyncResult);
        Console.WriteLine(string.Format("客戶端{0}請求連接...", client.RemoteEndPoint));
        AsyncSend(client, "服務器收到連接請求");
        AsyncSend(client, string.Format("歡迎你{0}",client.RemoteEndPoint));
        AsyncReveive(client);
      }, null);
    }

    /// <summary>
    /// 接收消息
    /// </summary>
    /// <param name="client"></param>
    private void AsyncReveive(Socket socket)
    {
      byte[] data = new byte[1024];
      try
      {
        //開始接收消息
        socket.BeginReceive(data, 0, data.Length, SocketFlags.None,
        asyncResult =>
        {
          int length = socket.EndReceive(asyncResult);
          Console.WriteLine(string.Format("客戶端發(fā)送消息:{0}", Encoding.UTF8.GetString(data)));
        }, null);
      }
      catch (Exception ex)
      {
        Console.WriteLine(ex.Message);
      }
    }

    /// <summary>
    /// 發(fā)送消息
    /// </summary>
    /// <param name="client"></param>
    /// <param name="p"></param>
    private void AsyncSend(Socket client, string p)
    {
      if (client == null || p == string.Empty) return;
      //數(shù)據(jù)轉碼
      byte[] data = new byte[1024];
      data = Encoding.UTF8.GetBytes(p);
      try
      {
        //開始發(fā)送消息
        client.BeginSend(data, 0, data.Length, SocketFlags.None, asyncResult =>
        {
          //完成消息發(fā)送
          int length = client.EndSend(asyncResult);
          //輸出消息
          Console.WriteLine(string.Format("服務器發(fā)出消息:{0}", p));
        }, null);
      }
      catch (Exception e)
      {
        Console.WriteLine(e.Message);
      }
    }
  }
}

客戶端

基本流程

1.創(chuàng)建套接字并保證與服務器的端口一致
2.使用BeginConnect()和EndConnect()這組方法向服務端發(fā)送連接請求
3.使用BeginSend()/EndSend和BeginReceive()/EndReceive()兩組方法與服務端進行收發(fā)通信
4.關閉套接字

代碼示例

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

namespace AsyncClient
{
  public class AsyncTCPClient
  {
    /// <summary>
    /// 連接到服務器
    /// </summary>
    public void AsynConnect()
    {
      //端口及IP
      IPEndPoint ipe = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6065);
      //創(chuàng)建套接字
      Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
      //開始連接到服務器
      client.BeginConnect(ipe, asyncResult =>
      {
        client.EndConnect(asyncResult);
        //向服務器發(fā)送消息
        AsynSend(client,"你好我是客戶端");
        AsynSend(client, "第一條消息");
        AsynSend(client, "第二條消息");
        //接受消息
        AsynRecive(client);
      }, null);
    }

    /// <summary>
    /// 發(fā)送消息
    /// </summary>
    /// <param name="socket"></param>
    /// <param name="message"></param>
    public void AsynSend(Socket socket, string message)
    {
      if (socket == null || message == string.Empty) return;
      //編碼
      byte[] data = Encoding.UTF8.GetBytes(message);
      try
      {
        socket.BeginSend(data, 0, data.Length, SocketFlags.None, asyncResult =>
        {
          //完成發(fā)送消息
          int length = socket.EndSend(asyncResult);
          Console.WriteLine(string.Format("客戶端發(fā)送消息:{0}", message));
        }, null);
      }
      catch (Exception ex)
      {
        Console.WriteLine("異常信息:{0}", ex.Message);
      }
    }

    /// <summary>
    /// 接收消息
    /// </summary>
    /// <param name="socket"></param>
    public void AsynRecive(Socket socket)
    {
      byte[] data = new byte[1024];
      try
      {
        //開始接收數(shù)據(jù)
        socket.BeginReceive(data, 0, data.Length, SocketFlags.None,
        asyncResult =>
        {
          int length = socket.EndReceive(asyncResult);
          Console.WriteLine(string.Format("收到服務器消息:{0}", Encoding.UTF8.GetString(data)));
          AsynRecive(socket);
        }, null);
      }
      catch (Exception ex)
      {
        Console.WriteLine("異常信息:", ex.Message);
      }
    }
  }
}


從總體上來講Socket異步編程的邏輯性更加明確了,因為我們只需要為每一個過程寫好回調(diào)函數(shù)就好了。那么這個示例的效果如何呢?我們來看看它的演示效果:

總結

和Socket同步編程的案例相比,今天的這個案例可能只是對Socket異步編程內(nèi)容的一個簡單應用,因為博主到現(xiàn)在為止都還沒有寫出一個可以進行交互聊天的程序來。在Socket的異步編程中,服務端不需要為一個客戶端單獨創(chuàng)建一個線程來維護其連接,可是這樣帶來的一個問題就是博主不知道該如何實現(xiàn)一個多客戶端的異步編程的實例。如果有朋友知道如何實現(xiàn)的話,還希望能夠告訴我,畢竟學習就是一個相互促進的過程啊。好了,最后想說的是博主這段時間研究Socket異步編程中關于異步方法調(diào)用的寫法問題。我們知道Socket異步編程中的方法是成對出現(xiàn)的,每一個方法都有一個回調(diào)函數(shù),對于回調(diào)函數(shù),這里有兩種寫法,以BeginConnect方法為例:

復制代碼 代碼如下:

m_Socket.BeginConnect(this.m_ipEndPoint,
        new AsyncCallback(this.ConnectCallBack),
        this.m_Socket);//其中ConnectCallBack是一個回調(diào)函數(shù)

或者

復制代碼 代碼如下:

m_Socket.BeginConnect(this.m_ipEndPoint,asyncResult=>
{
    //在這里添加更多代碼
},null)

博主為什么要在這里說這兩種寫法呢,有兩個原因:

* 第二種寫法更為簡潔,無需去構造容器傳遞Socket和消息,因為它們都是局部變量。如果我們使用第一種方法,因為主函數(shù)和回調(diào)函數(shù)是兩個不同的函數(shù),因此如果想要共享變量就需要通過IAsyncResult接口來訪問容器中的值,這樣顯然增加了我們的工作量。

* 第二種寫法更為優(yōu)雅,這似乎是C#語言中某種高級語法,具體叫什么我忘了,反正在Linq中經(jīng)常看到這種寫法的影子。

綜合以上兩個觀點,博主還是建議大家使用第二種寫法,博主打算有空的話將之前寫的程序再重新寫一遍,看看能不能找出代碼中的問題。好了,今天的內(nèi)容就是這樣了,謝謝大家,希望大家喜歡!

相關文章

最新評論