?? msgqueue.c
字號:
/*
* Copyright (c) 2000-2008
* Author: Weiming Zhou
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation.
*/
#ifdef _WIN32
#include <windows.h>
#endif
#include "CapiGlobal.h"
#include "DoubleList.h"
#include "MTask.h"
#include "MTList.h"
#include "MsgQueue.h"
#define DEFAULT_MSGQUEUE_LEN 65535
/** 消息隊列的創建函數
@param INT nMaxLen - 消息隊列的最大長度
@return MSGQUEUE * - 返回創建的消息隊列指針,失敗返回NULL
*/
MSGQUEUE * MsgQueue_Create(INT nMaxLen)
{
MSGQUEUE *pQueue;
pQueue = (MSGQUEUE *)malloc(sizeof(MSGQUEUE));
if ( pQueue != NULL )
{
pQueue->pSem = SemaCreate(0, nMaxLen);
if ( pQueue->pSem != NULL )
{
pQueue->nMaxLen = nMaxLen;
pQueue->pList = MTList_Create();
if ( pQueue->pList == NULL )
{
SemaClose(pQueue->pSem);
free(pQueue);
pQueue = NULL;
}
}
else
{
free(pQueue);
pQueue = NULL;
}
}
return pQueue;
}
/** 消息隊列的釋放函數
@param MSGQUEUE *pQueue - 消息隊列指針
@param DESTROYFUNC DestroyFunc - 數據釋放回調函數
@return void - 無
*/
void MsgQueue_Destroy(MSGQUEUE *pQueue, DESTROYFUNC DestroyFunc)
{
if ( pQueue != NULL )
{
INT nMaxLen;
if ( pQueue->nMaxLen > DEFAULT_MSGQUEUE_LEN )
{
nMaxLen = pQueue->nMaxLen;
}
else
{
nMaxLen = DEFAULT_MSGQUEUE_LEN;
}
SemaRelease(pQueue->pSem, nMaxLen ); /* 讓所有阻塞的接收操作可以繼續*/
MTList_Destroy(pQueue->pList, DestroyFunc);
SemaClose(pQueue->pSem);
free(pQueue);
}
}
/** 消息隊列的發送函數,將數據發送到消息隊列中
@param MSGQUEUE *pQueue - 消息隊列指針
@param void *pData - 要發送到消息隊列里的數據指針
@return INT - 同MTList_InsertTail()函數
*/
INT MsgQueue_Send(MSGQUEUE *pQueue, void *pData)
{
INT nRet;
nRet = MTList_InsertTail(pQueue->pList, pData);
SemaRelease(pQueue->pSem, 1); /* 將計數加1 */
return nRet;
}
/** 消息隊列的接收數據函數,從消息隊列中接收數據出來
@param MSGQUEUE *pQueue - 消息隊列指針
@return void * - 返回從消息隊列中接收到的數據
*/
void * MsgQueue_Recv(MSGQUEUE *pQueue)
{
SemaWait(pQueue->pSem); /* 將計數減1,計數為0則會阻塞住 */
return MTList_PopHead(pQueue->pList);
}
/** 消息隊列的枚舉初始化函數
@param MSGQUEUE *pQueue - 消息隊列指針
@return void - 無
*/
void MsgQueue_EnumBegin(MSGQUEUE *pQueue)
{
MTList_EnumBegin(pQueue->pList);
}
/** 消息隊列的枚舉下一個數據函數
@param MSGQUEUE *pQueue - 消息隊列指針
@param VISITFUNC VisitFunc - 數據訪問回調函數
@return INT - 同MTList_EnumNext()函數
*/
INT MsgQueue_EnumNext(MSGQUEUE *pQueue, VISITFUNC VisitFunc)
{
return MTList_EnumNext(pQueue->pList, VisitFunc);
}
#define MAX_QUEUE_SIZE 4096
#define MAX_LISTEN_SIZE 16
#define MAX_THREADS 10
#define DEFAULT_PORT 8080
#if 0
MSGQUEUE *g_pQue;
void ProcessRequest(void *args);
/** 初始化函數,初始化時會先創建消息隊列,并預創建MAX_THREADS個線程
@return INT - CAPI_FAILED表示失敗,CAPI_SUCCESS表示成功
*/
INT Init()
{
INT i;
g_pQue = MsgQueue_Create(MAX_QUEUE_SIZE);
if ( g_pQue == NULL )
{
return CAPI_FAILED;
}
for ( i = 0; i < MAX_THREADS; i++ )
{
_beginthread(ProcessRequest, 0, NULL);
}
return CAPI_SUCCESS;
}
/** 接收請求的處理函數
實現將接收到的請求的SOCKET標識符放入到消息隊列中
@return INT - CAPI_FAILED表示失敗,CAPI_SUCCESS表示成功
*/
INT RecvQuest()
{
struct sockaddr_in local, from;
SOCKET s, msgsock;
int fromlen;
s = socket(AF_INET, SOCK_STREAM, 0);
if (s == INVALID_SOCKET)
{
return CAPI_FAILED;
}
local.sin_family = AF_INET;
local.sin_addr.s_addr = INADDR_ANY;
local.sin_port = htons(DEFAULT_PORT);
if ( bind(s, (struct sockaddr*)&local, sizeof(local)) == SOCKET_ERROR)
{
return CAPI_FAILED;
}
if ( listen(s, MAX_LISTEN_SIZE ) == SOCKET_ERROR)
{
return CAPI_FAILED;
}
while( msgsock = accept(s, (struct sockaddr*)&from, &fromlen)
!= INVALID_SOCKET )
{
SOCKET *pNewSock = new SOCKET;
*pNewSock = msgsock;
MsgQueue_Send(g_pQue, (void *)pNewSock);
}
return CAPI_SUCCESS;
}
/** 處理請求的任務處理函數
這個函數是處理任務的入口函數,在里面處理接收客戶端發來的字符串“Hello!”,
并發送響應“OK"回客戶端。
@param void * -未使用
@return void -無
*/
void ProcessRequest(void *)
{
SOCKET *pSock;
while (pSock = MsgQueue_Recv(g_pQue))
{
int len;
char buf[1024];
len = recv(*pSock, buf, sizeof(buf)-1, 0);
if ( len > 0 )
{
buf[len] = '\0';
if ( strcmp(buf, "Hello!")== 0 )
{
strcpy(buf, "Ok");
send(*pSock, buf, strlen(buf), 0);
}
}
}
}
/** 將SOCKET信息打印到屏幕的回調函數
@param void *pData - 數據指針
@return INT - 取決于WriteToScreen()函數
*/
INT PrintAllIPToScreen(void *pData)
{
SOCKET *pSock = pData;
return WriteToScreen(*pSock);
#endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
減小字號
Ctrl + -