這是一個基於windows的,用C++編寫的用戶端伺服器程式,適合初學者,高手誤入.源碼必共用
思路是這樣的.啟動伺服器,伺服器啟動後會建立一個子線程,用於向用戶端發送資訊.用一個死迴圈用於接收用戶端的請求,用戶端請求成功後,會將用戶端的串連儲存到一個集合中,下面會詳細介紹這個儲存用戶端串連的類.用戶端串連成功後,伺服器會建立一個子線程用於接收用戶端的資訊,用戶端同樣也會建立一個子線程接收伺服器的資訊.這樣用戶端和伺服器就能進行通訊,如果有哪一方退出,另一方對應的接收資料的線程就會自動終止.
退出一個用戶端後,伺服器對應的接收資料的線程自動終止.如:
伺服器儲存用戶端串連的集合中會刪除對應的用戶端串連,由於這個刪除操作是在子線程中發生的,也就是說會有多個線程操作這個集合,那麼針對這個集合的操作必須是安全執行緒的.保證安全執行緒的方法又很多,我的這篇部落格《多線程編程--5種方法實現線程同步》介紹了5中方法實現線程同步,我這裡用的是關鍵段,還有一點值得說明的是,儲存用戶端串連的集合肯定只能有一份,我用一個類封裝了這個集合,這個類中的每個方法都是安全執行緒的,且只能有一個執行個體,這裡用了比較暴力的方法,將相關的方法設為private,提供一個public的方法返回這個對象的一個靜態執行個體,唯一的一個執行個體。
儲存用戶端串連的類如下:
//ClientList.h 存放用戶端的請求,只能有一個執行個體#ifndef _CLIENTLIST_H_#define _CLIENTLIST_H_#include <vector>#include "CSocket.h" #include <assert.h>class CSocket;class ClientList{public : typedef vector<CSocket*>::iterator Iter; void Add(CSocket* socket); int Count() const; CSocket* operator[](size_t index); void Remove(CSocket* socket); Iter Find(CSocket* socket); void Clear(); static ClientList* GetInstance() { static ClientList instance; return &instance; } ~ClientList();private: static CRITICAL_SECTION g_cs; static vector<CSocket*> _list; ClientList(); ClientList(const ClientList&); ClientList& operator=(const ClientList&); }; #endif
#include "ClientList.h"typedef vector<CSocket*>::iterator Iter; ClientList::ClientList(){ InitializeCriticalSection(&g_cs);//初始化g_cs的成員 }ClientList::~ClientList(){ DeleteCriticalSection(&g_cs);//刪除關鍵段 }void ClientList::Add(CSocket* socket){ if(socket!=NULL) { EnterCriticalSection(&g_cs);//進入關鍵段 _list.push_back(socket); LeaveCriticalSection(&g_cs);//退出關鍵段 }}int ClientList::Count() const{ return _list.size();}CSocket* ClientList::operator[](size_t index){ assert(index>=0 && index<_list.size()); return _list[index];}void ClientList::Remove(CSocket* socket){ Iter iter=Find(socket); EnterCriticalSection(&g_cs);//進入關鍵段 if(iter!=_list.end()) { delete *iter; _list.erase(iter); } LeaveCriticalSection(&g_cs);//退出關鍵段 }Iter ClientList::Find(CSocket* socket){ EnterCriticalSection(&g_cs);//進入關鍵段 Iter iter=_list.begin(); while(iter!=_list.end()) { if(*iter==socket) { return iter; } iter++; } LeaveCriticalSection(&g_cs);//退出關鍵段 return iter;}void ClientList::Clear(){ EnterCriticalSection(&g_cs);//進入關鍵段 for(int i=_list.size()-1;i>=0;i--) { delete _list[i]; } _list.clear(); LeaveCriticalSection(&g_cs);//退出關鍵段 }CRITICAL_SECTION ClientList::g_cs;vector<CSocket*> ClientList::_list ;
C++網路編程(一)