使用UDP(VC)发送接收日志

使用UDP(VC)发送接收日志

编者:李国帅

qq:9611153 微信lgs9611153

时间:2011/5/13

背景原因:

以前使用过此方法,好处是不会阻塞,当日志量比较大的时候能够快速反应。坏处就是udp发送大于最小传输单元的数据,或把不相关的数据连续密集发送,很可能造成数据错乱丢失。

 

发送:

 

//2011-9-29 10:51:01

//检查了一遍,发现mc中还是存在一些问题,log也不完善,可能丢数据,即便是进行了如下改造。

//udp不应该发送大于最小传输单元的数据,也不应该把不相关的数据连续密集发送,很可能造成数据错乱丢失。

#ifndef _M_LOG_H_
#define _M_LOG_H_

#include "stdio.h"
#pragma warning(disable : 4996)

#define LOG_EMERG   0   /* system is unusable */
#define LOG_ALERT   1   /* action must be taken immediately */
#define LOG_CRIT    2   /* critical conditions */
#define LOG_ERR  3   /* error conditions */
#define LOG_WARNING 4   /* warning conditions */
#define LOG_NOTICE  5   /* normal but significant condition */
#define LOG_INFO    6   /* informational */
#define LOG_DEBUG   7   /* debug-level messages */

#define LOG_ALREADY_INITED  -1
#define LOG_ERROR           -2
#define LOG_NOT_INITED      -3
#define LOG_GETSIZE_ERROR   -4

#define LOG_SEND_BUFFSIZE (1<<16)
#define NETWORK_MONITOR_PORT 3000

//#include  "winsock2.h"//#include "winsock.h"
//#pragma comment(lib, "Ws2_32.lib")//wsock32.lib

class CNetLog
{
public:
    CNetLog(int nPort)
    {
        m_nPort = nPort;
        strcpy(m_nDebugNetIP,"127.0.0.1");

        memset(&addrSendMinitor,0,sizeof(sockaddr_in));
        addrSendMinitor.sin_family      = AF_INET;
        addrSendMinitor.sin_addr.s_addr = inet_addr(m_nDebugNetIP);// 从配置文件获取 IP
        addrSendMinitor.sin_port        = htons(m_nPort); //NETWORK_MONITOR_PORT//NETWORK_MONITOR_PORT+1
        memset( &(addrSendMinitor.sin_zero),0,8);

        nsockSend=socket(AF_INET,SOCK_DGRAM,0);// UDP
        _ASSERT (nsockSend>0 && nsockSend < ((1<<16)-1));
        _ASSERT(nsockSend!=INVALID_SOCKET);

        memset(sendcontentbuf,0,LOG_SEND_BUFFSIZE);
    }
    ~CNetLog()
    {
        if (nsockSend>0)
        {
            closesocket(nsockSend);
        }
    }
public:
    void mlog(unsigned int level,const char *strHeader,const char *strInfo)
    {
        if (nsockSend<=0)return;

        time_t now;
        time(&now);
        struct tm localt;
        localtime_s(&localt,&now);

        int ret= 0;
        char * pInfo = NULL;
        int nlen = (int)strlen(strInfo);
        if (nlen<1200)
        {
            _snprintf_s(sendcontentbuf,LOG_SEND_BUFFSIZE,LOG_SEND_BUFFSIZE-1,"\n(%s:%d) (%04d/%02d/%02d %02d:%02d:%02d) %s",
                strHeader,level,localt.tm_year+1900, localt.tm_mon+1,localt.tm_mday, localt.tm_hour, localt.tm_min, localt.tm_sec,strInfo);
            sendcontentbuf[strlen(sendcontentbuf)] = 0;
            pInfo = (char *)sendcontentbuf;
            ret=sendto(nsockSend, pInfo, (int)strlen(pInfo)+1,0, (const sockaddr *)&addrSendMinitor, sizeof(addrSendMinitor));
            //ATLASSERT(ret>0);
        }
        else
        {
            _snprintf_s(sendcontentbuf,LOG_SEND_BUFFSIZE,LOG_SEND_BUFFSIZE-1,"\n(%s:%d) (%04d/%02d/%02d %02d:%02d:%02d)",
                strHeader,level,localt.tm_year+1900, localt.tm_mon+1,localt.tm_mday, localt.tm_hour, localt.tm_min, localt.tm_sec);
            pInfo = (char *)sendcontentbuf;
            nlen = (int)strlen(pInfo);
            sendcontentbuf[nlen] = 0;
            ret=sendto(nsockSend, pInfo,nlen+1 ,0, (const sockaddr *)&addrSendMinitor, sizeof(addrSendMinitor));

            pInfo = (char *)strInfo;
            nlen = (int)strlen(pInfo)+1;
            int npacket = nlen/1000;
            int nlen_per = 0;
            if((nlen%1000)>0)npacket++;
            for (int i=0;i<npacket;i++)
            {
                if(nlen>=1000)
                {
                    nlen_per = 1000;
                }
                else
                {
                    nlen_per = nlen;
                }
                strncpy(sendcontentbuf,pInfo,nlen_per);
                sendcontentbuf[nlen_per] = 0;

                int ret=sendto(nsockSend, sendcontentbuf,nlen_per+1 ,0, (const sockaddr *)&addrSendMinitor, sizeof(addrSendMinitor));
                //ATLASSERT(ret>0);
                if (ret < 0)OutputDebugString("mlog:sendto fail.\n");
                nlen = nlen - nlen_per;
                pInfo = pInfo+nlen_per;
            }
        }
    }

private:
    char  m_nDebugNetIP[60];// host IP
    int m_nPort;

    SOCKET nsockSend;// global sock for debug log
    struct sockaddr_in addrSendMinitor;
    TCHAR sendcontentbuf[LOG_SEND_BUFFSIZE];

};

#endif

 

接收测试:

// Win32Test.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"

#include <tchar.h>

#include <stdio.h>
#include <io.h>
#include <assert.h>
#include <stdlib.h>

#include <windows.h>

#include  "winsock2.h"//#include "winsock.h"
#pragma comment(lib, "Ws2_32.lib")//wsock32.lib

#define VMS_BUFFSIZE 2048
int main(int argc, char* argv[])
{
    WORD wVersionRequested = MAKEWORD(2,2);
    WSADATA wsa;

    int err = WSAStartup(wVersionRequested,&wsa);
    if (err !=0)return -1;

    int sock1=socket(AF_INET,SOCK_DGRAM,0);
    if (INVALID_SOCKET == sock1)return -1;
    char op = 1;
    setsockopt(sock1,SOL_SOCKET,SO_REUSEADDR,&op,sizeof(int));

    sockaddr_in addr;
    memset(&addr,0,sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port =htons(3000);
    addr.sin_addr.s_addr = ADDR_ANY;
    bind(sock1,(sockaddr*)(&addr),sizeof(addr));

    sockaddr_in from;
    int fromlen = sizeof(sockaddr_in);

    char* pMsg = (char *)malloc(VMS_BUFFSIZE);
    int nMsgLen=0;

    int i = 10000000;
    while(i-->0)
    {
        struct timeval timeout;
        fd_set readfds;
        FD_ZERO(&readfds);
        FD_SET(sock1, &readfds);
        timeout.tv_sec = 0;
        timeout.tv_usec = 1000;
        int err = select(1, &readfds, NULL, NULL, &timeout);    
        if(err == 0){  //timeout            
            continue;
        }
        if(err < 0){
            printf("SursvrCom select error %d", WSAGetLastError());
            continue;
        }

        nMsgLen = recvfrom(sock1, (char *)pMsg, VMS_BUFFSIZE, 0, (struct sockaddr*)&from, &fromlen);
        if(nMsgLen<=0){
            continue;
        }
        printf("%s", (char *)pMsg);
    }

    free(pMsg);
    //shutdown(sock1,SD_BOTH);
    closesocket(sock1);
    WSACleanup();
    system( "PAUSE" );
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

微澜-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值