作者:吳康彬
    采用CS方式的程序不可避免都要碰到socket連接的問題,很多時候,使用編程語言當中自帶的socket庫,使用起來多少有些不習慣,雖然系統自帶的庫在很多異常處理,穩定性上下了很多功夫,但是要去理解和使用那些庫,比如做socket連接池不免要走很多彎路。在這里我和大家討論下怎么樣創建和使用socket鏈接池。 
    一般socket鏈接有以下兩種方式:長(常)鏈接和短鏈接。 
    長鏈接:當數據發送完成后socket鏈接不斷開。一直保留到異?;蛘呤浅绦蛲顺鰹橹梗@種方式的好處是不用每次去發起連接斷開,在速度上可以比短連接要快一些,但是相對來說對服務器的資源壓力也要大些。長鏈接用的范圍很廣,比如游戲系統,QQ等等,長(常)鏈接一般還需要定時向服務器ping數據,以保證socket鏈接暢通。當ping不通服務器時,需要重新開啟鏈接。 
    短鏈接:當一次數據發送完畢后,主動斷開鏈接,每次發送數據都要一次鏈接、斷開操作,這種方式的好處是:對服務器的資源占用相對來說比較小,但是由于每次都要重新鏈接,速度開銷上也比較大,這種方式對于那種不需要經常與服務器交互的情況下比較適用。 
    上面兩種方法在用戶量非常大的情況下都存在著很大的不足,因此,我們考慮可以用一種折衷的辦法,那就是使用socket的連接池。 
    程序一開始初始化創建若干數量的長鏈接。給他們設置一個標識位,這個標識位表示該鏈接是否空閑的狀態。當需要發送數據的時候,系統給它分配一個當前空閑的鏈接。同時,將得到的鏈接設置為“忙”,當數據發送完畢后,把鏈接標識位設置為“閑”,讓系統可以分配給下個用戶,這樣使得兩種方式的優點都充分的發揮出來了。杭州攜購網絡科技有限公司旗下的攜購獨立購物網(http://www.shopxg.com)系統采用的就是這種方式。用戶數量足夠多的時候,只需要動態增加鏈接池的數量即可。 
    下面我們用具體的程序來講解下: 
    首先我們聲明一個socket類: 
 public class XieGouSocket
 {
  public Socket m_socket;  //Socket對象
  public bool m_isFree;  //判斷是否空閑
  public int m_index;  //在鏈接緩存池中的索引值
 }
 
    下面的函數是創建socket鏈接池,這里為了使代碼更加清晰,我特地把異常處理部分全部取掉了。 
 public XieGouSocket[] m_socket; //先定義個緩沖池
 public void  CreateSocketPool()
 {
  string ip= “127.0.0.1”; 
  string port= 2003; 
  IPAddress serverIp=IPAddress.Parse(ip); 
  int serverPort=Convert.ToInt32(port); 
  IPEndPoint iep=new IPEndPoint(serverIp,serverPort); 
  m_socket = new XieGouSocket[200]; 
  for(int i =0; i < 200 ; i ++)
  {
   m_socket[i] = new XieGouSocket();
   m_socket[i].m_index = i ;
   m_socket[i].m_isFree = true;
   m_socket[i].m_socket =new Socket(AddressFamily.InterNetwork,SocketType.Stream,PRotocolType.Tcp);
   m_socket[i].m_socket.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.SendTimeout,1000);  
   m_socket[i].m_socket.Connect(iep);
  }
 }
    下面的函數是獲取當前空閑的socket鏈接: 
    因為是多線程,所以我們需要加一個原子操作,定義一個原子變量,以防止多個線程之間搶占資源問題的發生。 
 private   static   Mutex   m_mutex=new   Mutex();
 public static  XieGouSocket GetFreeConnection()
 { 
  m_mutex.WaitOne(); //先阻塞
  for(int i =0; i < m_socket.Length ; i ++)
  {
   if(m_socket[i].m_isFree) //如果找到一個空閑的
   {
    m_socket[i].m_isFree = false;
    m_mutex.ReleaseMutex();//釋放資源          
    return m_socket[i];
   }
  }
  //如果沒有空閑的鏈接,要么等待,要么程序再動態創建一個鏈接。
  m_mutex.ReleaseMutex();//釋放資源
     
  return null;
 }
    當數據發送完畢后,程序必須將m_isFree 設置為 False。否則只使用不釋放,程序很快就溢出了。 
    基本的思路就是這樣的,大家可以在此基礎上好好的改進下,這樣運行的效率就比較高了。 
        歡迎大家與我交流。QQ:8814730 Email:wkb@xiegoo.com
新聞熱點
疑難解答