采用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:[email protected]