码迷,mamicode.com
首页 > 其他好文 > 详细

简单连接池实现

时间:2015-05-25 18:07:00      阅读:133      评论:0      收藏:0      [点我收藏+]

标签:

 1 #ifndef _SOCKET_MANAGE_H_
 2 #define _SOCKET_MANAGE_H_
 3 
 4 #define MAX_SRV_NUM        100
 5 #define DIGEST_LEN        20
 6 #define MAX_BUF_SISE    4096
 7 
 8 typedef struct
 9 {
10     unsigned int uiPort;            //端口
11     unsigned char ucArrIp[64];        //ip字符串
12     unsigned char ucArrPwd[64];        //Api口令
13     unsigned int uiEncPwdLen;        //哈希过后的api口令长度
14     unsigned char ucArrEncPwd[64];    //哈希过后的api口令
15 } SrvInfo_St;
16 
17 
18 typedef struct
19 {
20     int uiSrvId;                    //该结构体中socket句柄对应的Server在SrvInfo_St结构体数组中的索引
21     int uiArrIndex;                    //本结构体在Handle_St结构体数组中的索引
22     int uiSocket;                    //真正的socket句柄
23     Sem sem;
24 } Handle_St;
25 
26 
27 #endif
  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #include <Windows.h>
  5 
  6 #include "SocketManage.h"
  7 
  8 #pragma comment(lib, "Ws2_32.lib")
  9 
 10 #define SML_BUFF_LEN 128
 11 #define LRG_BUFF_LEN 4096
 12 
 13 //-------------------------------------------------------------------------------
 14 
 15 Mutex LOCK_Init;
 16 Mutex LOCK_Handle;
 17 
 18 int InitFlag = 0;            //大于0代表已经初始化过
 19 int TimeOut = 0;            //超时时长
 20 int ServerNum = 0;            //签名服务器数量
 21 
 22 int HandleMaxNum = 0;        //最大需要创建的Socket句柄数
 23 int HandleNum = 0;            //已经创建的Socket句柄数
 24 Handle_St* pHandle = NULL;    //所有Socket句柄和服务器索引的对应
 25 
 26 
 27 int FreeBgnIndex = 0;        //从前面开始取,指向第一个可用的句柄
 28 int FreeEndIndex = 0;        //从后面开始放,指向即将放入句柄的索引,即最后一个可用句柄索引的下一个
 29 
 30 int *pFreeIndex = NULL;        //空闲Socket句柄索引缓存,值为Handle_St数组的索引
 31 
 32 
 33 SrvInfo_St SrvInfos[MAX_SRV_NUM];    //存放服务器信息
 34 
 35 //    上一个连接的索引
 36 int LastConnectIndex = 0;
 37 
 38 //-------------------------------------------------------------------------------
 39 
 40 //    获取下一个会话索引
 41 int GetNextHandleIndex()
 42 {
 43     int j = 0;
 44 
 45     j = LastConnectIndex;
 46 
 47     do
 48     {
 49         j = (j +1 )% HandleMaxNum;
 50 
 51         LastConnectIndex = j;
 52 
 53         return LastConnectIndex;
 54 
 55     } while (j != LastConnectIndex);
 56 
 57     return -1;
 58 }
 59 
 60 //    对所有签名服务器增加一个连接
 61 int AllConnect()
 62 {
 63     
 64     int ret = 0;
 65     int sockfd = 0;
 66     int srvId = 0;
 67 
 68     for(srvId = 0; srvId < ServerNum; srvId ++)
 69     {    
 70         //需要考虑某Srv出错??
 71         ret = Socket_Conn((char *)SrvInfos[srvId].ucArrIp, SrvInfos[srvId].uiPort, TimeOut, &sockfd);
 72         if ( 0 != ret)
 73             return Err_Connect2Server;
 74         else
 75         {
 76             //将新创建的句柄赋到句柄数组中
 77             pHandle[HandleNum].uiSocket = sockfd;
 78             
 79             pHandle[HandleNum].uiSrvId = srvId;
 80 
 81             pHandle[HandleNum].uiArrIndex = HandleNum;
 82 
 83             InitSem(&pHandle[HandleNum].sem);
 84             
 85             //放入空闲句柄缓存
 86             pFreeIndex[FreeEndIndex++] = HandleNum;
 87 
 88             //指向下一个即将放入的句柄索引自增
 89             HandleNum++;
 90             
 91         }
 92         
 93     }
 94 
 95     return 0;
 96 }
 97 
 98 //    从pFreeIndex中取出空闲的Socket句柄索引
 99 int GetFreeAvalSocket(Handle_St * pHdl)
100 {
101     int i = 0;
102     int ret = 0;
103 
104     //index为空闲的Socket句柄的索引
105     int index = pFreeIndex[FreeBgnIndex];
106 
107     if(-1 != index)    //有空闲句柄
108     {
109         pHdl->uiSocket = pHandle[index].uiSocket;
110         pHdl->uiSrvId = pHandle[index].uiSrvId;
111 
112         pHdl->uiArrIndex = pHandle[index].uiArrIndex;
113 
114 
115         //取出来以后把原来的设为不可用
116         pFreeIndex[FreeBgnIndex] = -1;
117         
118         //把可用的索引加一,指向下一个可用的
119         FreeBgnIndex ++;
120         
121         //如果FreeBgnIndex指到头了以后重新改为指向第一个
122         if(FreeBgnIndex == HandleMaxNum)
123             FreeBgnIndex = 0;
124     }
125     else    //没有空闲句柄
126     {        
127         return -1;
128     }
129 
130     return 0;
131 }
132 
133 //    如果哪一台机器有可用的空闲句柄就用哪台机器
134 //    如果所有的机器都没有空闲句柄,就所有机器再加一次连接
135 int GetAvalSocket(Handle_St * pHdl)
136 {
137     int i = 0;
138     int ret = 0;
139 
140     ret = GetFreeAvalSocket(pHdl);
141 
142     if(0 != ret)    //没有空闲的句柄
143     {
144         if(HandleNum >= HandleMaxNum)    //句柄数已经达到最大数值
145         {        
146             int UsableHandleIndex = GetNextHandleIndex();
147             pHdl->uiArrIndex = UsableHandleIndex;
148             pHdl->uiSocket = pHandle[UsableHandleIndex].uiSocket;
149             pHdl->uiSrvId = pHandle[UsableHandleIndex].uiSrvId;
150             ret = 0;
151 
152         }
153         else
154         {
155             ret = AllConnect();
156             if(0 != ret) return ret;
157                 
158             ret = GetFreeAvalSocket(pHdl);
159             if(0 != ret) return ret;
160 
161         }
162 
163     }
164 
165     return ret;
166 
167 }
168 
169 //    将不用的连接重新放入对应Srv的空闲句柄缓存中
170 int FreeAvalSocket(Handle_St *pHdl)
171 {
172     if(FreeEndIndex == HandleMaxNum)
173         FreeEndIndex = 0;
174 
175     pFreeIndex[FreeEndIndex] = pHdl->uiArrIndex;
176 
177     FreeEndIndex++;
178 
179 
180     pHdl->uiArrIndex = -1;
181     pHdl->uiSocket = -1;
182     pHdl->uiSrvId = -1;
183 
184     return 0;
185 }
186 
187 //    对于已经不可用的连接进行重连
188 int ReConnect(Handle_St *pHdl)
189 {
190     int ret = 0;
191     int sockfd = 0;
192 
193     int srvId = 0;
194 
195     MutexLock(&LOCK_Handle);
196 
197     srvId = pHdl->uiSrvId;
198 
199     close(pHdl->uiSocket);
200 
201     ret = Socket_Conn((char *)SrvInfos[srvId].ucArrIp, SrvInfos[srvId].uiPort, TimeOut, &sockfd);
202     if(0 == ret)
203         pHdl->uiSocket = sockfd;
204     
205     MutexUnLock(&LOCK_Handle);
206     return ret;
207 
208 }
209 
210 int CheckSockFd(int sockFd)
211 {
212     if(0 > sockFd || sockFd >= HandleMaxNum)
213         return Err_InvalidData;
214     else 
215         return 0;
216 }
217 
218 //-------------------------------------------------------------------------------
219 
220 int InitMoudle()
221 {
222     InitMutex(&LOCK_Init);
223     InitMutex(&LOCK_Handle);
224 
225     return 0;
226 }
227 
228 int InitServer(const char *pucIpStr, const char *puiPortStr, const int uiTimeOut, 
229     const char *pucApiPasswdStr, const int uiMaxConnection)
230 {
231     int ret = 0;
232     int i = 0;
233     int j = 0;
234     int sockfd = 0;
235 
236     MutexLock(&LOCK_Init);
237 
238     if(0 < InitFlag)
239     {
240         MutexUnLock(&LOCK_Init);
241         return 0;
242     }
243 
244     TimeOut = uiTimeOut /1000;
245     memset(SrvInfos, 0x00, MAX_SRV_NUM * sizeof(SrvInfo_St));
246 
247     //-------------------------------------------------------------------------------
248     //将IP字符串、端口字符串、Pwd字符串转换到SrvInfos数组中保存
249     //ret = SrvInfoFmt(pucIpStr, strlen(pucIpStr), puiPortStr, strlen(puiPortStr), 
250     //    pucApiPasswdStr, strlen(pucApiPasswdStr), SrvInfos, &ServerNum);
251     //if(0 != ret) return Err_InvalidData;
252 
253     ServerNum = 1;
254     SrvInfos[0].uiPort = atoi(puiPortStr);
255     memcpy(SrvInfos[0].ucArrIp, pucIpStr, strlen(pucIpStr));
256     
257     //-------------------------------------------------------------------------------
258 
259     //计算所有签名服务器最大连接数,一定为Srv数目的倍数
260     if(0 != uiMaxConnection % ServerNum)
261         HandleMaxNum = uiMaxConnection + ServerNum - uiMaxConnection % ServerNum;
262     else
263         HandleMaxNum = uiMaxConnection;
264 
265     //将上一次连接的索引初始化为最大连接数减1。
266     LastConnectIndex = HandleMaxNum - 1;
267 
268     //空闲句柄索引缓存分配
269     pFreeIndex = (int *)calloc(HandleMaxNum, sizeof(int));
270 
271     //所有句柄缓存初始化
272     pHandle = (Handle_St*)calloc(HandleMaxNum, sizeof(Handle_St));
273 
274     for(i = 0 ;i < HandleMaxNum; i ++)
275     {
276         pHandle[i].uiSocket = -1;
277         pHandle[i].uiSrvId = -1;
278         pHandle[i].uiArrIndex = -1;
279 
280         pFreeIndex[i] = -1;
281 
282     }
283 
284     //每个Srv连接一次,连接后将句柄保存在数组中
285     //需要考虑某Srv出错??
286     ret = AllConnect();
287 
288     InitFlag++;
289 
290     MutexUnLock(&LOCK_Init);
291 
292 
293     return ret;
294 }
295 
296 
297 int GetConnection(int *psockFd)
298 {
299     Handle_St Handle;
300 
301     MutexLock(&LOCK_Handle);
302 
303     memset(&Handle, 0x00, sizeof(Handle_St));
304 
305     GetAvalSocket(&Handle);
306 
307     *psockFd = Handle.uiArrIndex;
308 
309     MutexUnLock(&LOCK_Handle);
310 
311     return 0;
312 }
313 
314 int CloseConnection(int sockFd)
315 {
316     Handle_St Handle;
317 
318     if(0 != CheckSockFd(sockFd))
319         return Err_InvalidData;
320 
321     MutexLock(&LOCK_Handle);
322 
323     Handle.uiArrIndex = sockFd;
324     Handle.uiSocket = pHandle[sockFd].uiSocket;
325     Handle.uiSrvId = pHandle[sockFd].uiSrvId;
326 
327     FreeAvalSocket(&Handle);
328 
329     MutexUnLock(&LOCK_Handle);
330 
331     return 0;
332 }

 

简单连接池实现

标签:

原文地址:http://www.cnblogs.com/ggxxjj123/p/4528362.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!