基于Mailslot(邮槽)技术的日志服务程序的实现

61 篇文章 0 订阅
36 篇文章 0 订阅

因项目需要,写了个基于邮槽技术的log server,运行起来相当的不错,摆脱了fwrite等直接写log方法的不好的地方,分享如下。

#include "stdafx.h"
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>
#include <iostream>

#define MAILSLOT_LOG_SERVER_NAME TEXT("\\\\.\\mailslot\\mailslot_log_server"

static HANDLE hSlot = INVALID_HANDLE_VALUE;
static DWORD  g_ulLogsCount = 0;


BOOL ReadSlot() 

DWORD cbMessage, cMessage, cbRead; 
BOOL fResult; 
LPTSTR lpszBuffer; 
TCHAR achID[80]; 
DWORD cAllMessages; 
HANDLE hEvent;
OVERLAPPED ov;


cbMessage = cMessage = cbRead = 0; 


fResult = GetMailslotInfo( hSlot, // mailslot handle 
(LPDWORD) NULL,               // no maximum message size 
&cbMessage,                   // size of next message 
&cMessage,                    // number of messages 
(LPDWORD) NULL);              // no read time-out 


if (!fResult) 

printf("GetMailslotInfo failed with %d.\n", GetLastError()); 
return FALSE; 



if (cbMessage == MAILSLOT_NO_MESSAGE) 

//printf("Waiting for a message...\n"); 
return TRUE; 



cAllMessages = cMessage; 


hEvent = CreateEvent(NULL, FALSE, FALSE, TEXT("EemsSlotEvent"));
if( NULL == hEvent ) {
printf("Create overlap event failed !!! \n"); 
return FALSE;
}
ov.Offset = 0;
ov.OffsetHigh = 0;
ov.hEvent = hEvent;


while (cMessage != 0)  // retrieve all messages

// Create a message-number string. 
#if(1)
if (g_ulLogsCount >= 0x10000) {
StringCchPrintf((LPTSTR) achID,  80, TEXT("%lx "),   g_ulLogsCount + 1); 
} else {
StringCchPrintf((LPTSTR) achID,  80, TEXT("%04lx "), g_ulLogsCount + 1); 
}
#else
StringCchPrintf((LPTSTR) achID, 
80,
TEXT("[#%d.%d] "), 
cAllMessages - cMessage + 1, 
cAllMessages); 
#endif
// Allocate memory for the message. 


int iDestLength = lstrlen((LPTSTR) achID) * sizeof(TCHAR) + cbMessage;


lpszBuffer = (LPTSTR) GlobalAlloc(GPTR, iDestLength + 1); 
if( NULL == lpszBuffer )
return FALSE;
lpszBuffer[0] = '\0'; 


StringCbCopy(lpszBuffer, iDestLength, achID);


fResult = ReadFile(hSlot, 
lpszBuffer + iDestLength - cbMessage, 
cbMessage, 
&cbRead, 
&ov); 


if (!fResult) 

printf("ReadFile failed with %d.\n", GetLastError()); 
CloseHandle(hEvent);
GlobalFree((HGLOBAL) lpszBuffer); 
return FALSE; 



// Concatenate the message and the message-number string. 


//StringCbCat(lpszBuffer, 
// lstrlen((LPTSTR) achID)*sizeof(TCHAR)+cbMessage, 
// (LPTSTR) achID); 


// Display the message. 


_tprintf(TEXT("%s\n"), lpszBuffer); 
g_ulLogsCount++;


GlobalFree((HGLOBAL) lpszBuffer); 


fResult = GetMailslotInfo(hSlot,  // mailslot handle 
(LPDWORD) NULL,               // no maximum message size 
&cbMessage,                   // size of next message 
&cMessage,                    // number of messages 
(LPDWORD) NULL);              // no read time-out 


if (!fResult) 

CloseHandle(hEvent);
printf("GetMailslotInfo failed (%d)\n", GetLastError());
return FALSE; 


CloseHandle(hEvent);
return TRUE; 
}


BOOL WINAPI MakeSlot(LPTSTR lpszSlotName) 

hSlot = CreateMailslot(lpszSlotName, 
0,                             // no maximum message size 
MAILSLOT_WAIT_FOREVER,         // no time-out for operations 
(LPSECURITY_ATTRIBUTES) NULL); // default security


if (hSlot == INVALID_HANDLE_VALUE) 

printf("CreateMailslot failed with %d\n", GetLastError());
return FALSE; 

else
{
printf("Mailslot created successfully.\n"); 
}
return TRUE; 
}


//线程处理函数
DWORD WINAPI RecvThreadProc(LPVOID lpParam)
{
HANDLE hRecvMailSlot = (HANDLE)lpParam;
DWORD   dwWaitResult; 


while (INVALID_HANDLE_VALUE != hRecvMailSlot) {
dwWaitResult = WaitForSingleObject(hRecvMailSlot, INFINITE);
try { 
switch (dwWaitResult) 
{
case WAIT_OBJECT_0: 
ReadSlot();
break; 


case WAIT_ABANDONED: 
CloseHandle(hRecvMailSlot);
hRecvMailSlot = INVALID_HANDLE_VALUE;
break;
}
}
catch(...)

// Handle error.
CloseHandle(hRecvMailSlot);
hRecvMailSlot = INVALID_HANDLE_VALUE;
}
Sleep(50);
}


if (INVALID_HANDLE_VALUE != hRecvMailSlot) {
//关闭邮槽
CloseHandle(hRecvMailSlot);
}


return NULL;
}


//
void SetColor(unsigned short ForeColor=4,unsigned short BackGroundColor=0) //给参数默认值,使它可以接受0/1/2个参数
{
HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE); //本例以输出为例
SetConsoleTextAttribute(hCon, ForeColor | BackGroundColor);
};


int _tmain(int argc, _TCHAR* argv[])
{
SetConsoleTitle("Mailslots Log Server Running ...");


CONSOLE_SCREEN_BUFFER_INFO csbiInfo; 
// Get handles to STDIN and STDOUT. 
HANDLE hStdout; 
hStdout = GetStdHandle(STD_OUTPUT_HANDLE); // Save the current text colors. 
if (GetConsoleScreenBufferInfo(hStdout, &csbiInfo)) 
{
WORD wOldColorAttrs = csbiInfo.wAttributes; 
// Set the text attributes to draw red text on black background. 
if (SetConsoleTextAttribute(hStdout, FOREGROUND_GREEN | FOREGROUND_INTENSITY))
{
std::cout << "-----------------------------------------------------------------------" << std::endl;
SetConsoleTextAttribute(hStdout, wOldColorAttrs);
}
}


if (MakeSlot(MAILSLOT_LOG_SERVER_NAME)) {
HANDLE hThread = CreateThread(NULL, 0, RecvThreadProc, hSlot, 0, NULL);
WaitForSingleObject(hThread, INFINITE);
}
return 0;
}

在客户端,CreateFile(MAILSLOT_LOG_SERVER_NAME,...) 然后再WriteFile就可以了,非常地简单


如果在dll中实现客户端,并实现Singleton模式,可以实现在各个DLL和exe访问同一个客户端,这样,讨厌的在各个DLL插件中不能输出log的情况一并解决。如果要实现log分级,需要修改上述的代码,如果不嫌麻烦,可以将log分级按不同颜色输出,帅呆了!




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值