@田伯光
多个进程指向同一个文件的话,的确都可以写进去。至于是不是稳定就不清楚了,呵呵,我一直是单进程多线程下使用,偶尔忘记程序已经启动,第二次启动,同样会把log写进文件。
你多测试下吧。
log4cplus的配置文件的配置方式网上不少,或者你留个邮箱,我发给你。
@mono,给你个可以编译通过的宏,不知道你是win下还linux下,下面的宏都可以,另外流式的log不容易和printf、ace等对应,也看个人喜好,我是认为printf的方式更容易格式化输出。
#define USE_LOG4CPLUS
#ifdef USE_LOG4CPLUS
#include <log4cplus/configurator.h>
#include <string>
static log4cplus::Logger logger= log4cplus::Logger::getInstance("Log");
static void init_log(const std::string & path)
{
log4cplus::PropertyConfigurator::doConfigure(path);
}
#define XLOG_ALL log4cplus::TRACE_LOG_LEVEL
#define XLOG_TRACE log4cplus::TRACE_LOG_LEVEL
#define XLOG_DEBUG log4cplus::DEBUG_LOG_LEVEL
#define XLOG_INFO log4cplus::INFO_LOG_LEVEL
#define XLOG_NOTICE log4cplus::INFO_LOG_LEVEL
#define XLOG_WARNING log4cplus::WARN_LOG_LEVEL
#define XLOG_ERROR log4cplus::ERROR_LOG_LEVEL
#define XLOG_CRITICAL log4cplus::FATAL_LOG_LEVEL
#ifdef WIN32
#if (_MSC_VER < 1500)
#define vsnprintf _vsnprintf
#endif
void inline win_log( int l, const char *format, ... )
{
if(logger.isEnabledFor(l)) {
schar buf[2046]={0};
va_list list;
va_start( list, format );
vsnprintf( buf, (size_t)2045,format, list );
va_end( list );
logger.forcedLog(l, buf, __FILE__, __LINE__);
}
}
#define X_LOG win_log
#else
#define X_LOG(l, ...) \
do { \
if(logger.isEnabledFor(l)) { \
char __buf__internal__[2046]={0}; \
snprintf(__buf__internal__,2045,__VA_ARGS__); \
logger.forcedLog(l, __buf__internal__, __FILE__, __LINE__); \
} \
} while(0)
#endif
@guosha
没有用过。
log是个小功能,封装下能做到透明使用基本就可以了。log4c依赖apr库,如果你的主体程序不是在apr上构建的话,引入log4c不太舒服,呵呵。
。。。。。。。。。。。
路过。。。。。。。。。
。。。。。。。。。。。
@mono
#define USE_LOG4CPLUS
之后就编译正确了吧,或者你把define USE_ACE_LOG那段去掉,可以用printf调式。
你的需求是什么样子的?我用于server端程序,在main函数开始,来句:
#ifdef USE_LOG4CPLUS
init_log("./log.properties");
#endif
之后就再就是正常的程序启动了,起各个协议栈、线程。当然log也都是打印在一个log文件里。
server端程序是一直运行的,不会退出,也就不存在消亡的问题。
re: 【原创】技术系列综述(二) [未登录] cppexplore 2008-11-10 09:36
@true
业务线程也不见得是多线程实现,尤其是是处理有上下文关联关系(比如,rtsp协议,发了setup,才能发play,发送teardown之后才结束,不同阶段状态是不同的,http是无状态的协议就另说了)逻辑的业务线程 ,一般都是单线程。把握住系统瓶颈的所在,在关键业务瓶颈处加多线程。另外,如果真想实现你说的情况,可以绑定connection和上层业务线程,我觉得这不会有性能的提升,当然也要看你的业务应用场景。
re: 网上大多数原理总结,UDP打洞原理[未登录] cppexplore 2008-10-27 19:42
@伐木鼎鼎
呵呵,没那么严重,可以做丢包重传机制,这样第一次a发给b的包可能会被拒收,第一个b发给a的也可能被拒收,但后面的包就正常了。
re: 【原创】技术系列之 线程(一) cppexplore 2008-10-23 15:39
@cui
呵呵,那是线程(二)中说的。
开始写文章有不少错误的认识,后来对问题的看法再不停的调整,但旧有的文章中有的错误说法一直没有更正。这篇文章里的信号量就是一例。
re: 【原创】技术系列综述(一) cppexplore 2008-10-23 15:02
@powervv
不错。二进制包更多的是对字节序、字节对齐问题的深入。关键的地方还是struct结构的准确定义,包括大小端、字节对齐问题。幸好一般协议在定义的时候,都会注意字节对齐问题,不够1字节也会加padding补充,呵呵。
除了字节补充完成外,一般也都会保证4字节对齐完成,因此文中举例的3字节结构体实际中是不存在的,即便是不要额外信息,协议也会在seq前规定1字节的padding补充满4字节,在seq前补充也是为了避免设置pack(1)。
感谢补充!
re: 【原创】技术系列之 线程(二)[未登录] cppexplore 2008-10-23 13:43
@cui
多谢。最近看到了,这个是信号安全的系统调用。
re: 【原创】技术系列综述(一)[未登录] cppexplore 2008-10-23 12:09
@小鱼
忘记说et下的fd要设置非阻塞,其实多路复用函数下的fd一般都是非阻塞模式。虽然要减少read的次数,即便是lt模式下,也不能数据少就不读,呵呵。ET下数据没读完,这个fd就永远不会有事件上来了。et是边缘触发,就是从无数据到有数据这个变化点会触发,lt是水平触发,只要socket缓冲区有数据(当低潮属性设置为1的时候,默认也是1)就会触发。
re: 【原创】技术系列综述(一)[未登录] cppexplore 2008-10-23 12:02
ET模式下fd可读 就要一直读到返回-1并且errno是EAGAIN(信号中断产生的EINTR要继续)。可以man epoll看到。
...............
首页上,你上篇文章之前的文章就是有关 成员函数委托 的,两篇文章紧挨着
@创
listen后 accept前加fork是常见的设计,在不使用多路复用函数的情况下
@luke
区别就是fork前生成fd ,会导致多个进程在相同epoll上wait
想法不错,把accept前的多进程用于多路复用函数,完美的方案,呵呵。
现实世界往往都不是那么完美。
还没看到过select poll epoll类的应用前面可以加fork做这种领导者模型的。想想也不太现实,即使可以多进程select,那么一个被唤醒后,读数据前,另一个也一定会被唤醒,这样还是和单进程一样。
re: 模版函数指针,C++委托的实现-原创[未登录] cppexplore 2008-09-30 12:46
非常不错!
强大的消息映射、状态机事件映射都要靠这个才能完美的解决成员函数的问题。
re: 消息映射机制的简单实现[未登录] cppexplore 2008-09-30 12:32
顶一下
前几天我也刚写了一个,用在线程消息的处理中,我的消息类型做数组下标了,直接定位取处理函数,这都是无关紧要的细节。关键在ON_COMMAND宏的展现方式,我的处理线程消息,名字起做ON_MESSAGE
整体思路基本都是一样的,呵呵。
re: 【原创】测试系列之 陪测程序示例[未登录] cppexplore 2008-08-12 10:18
@flw
好东西 非常感谢
来拜拜牛人!
太牛了!!!!!!!!!!!!!!!
个人有的项目用异常,有的不用,感觉不用异常能对代码的控制力更强,近来的项目已经不用异常了。感觉不到用异常的好处。
“当构造失败时只有异常可以处理”,此处构造失败是值什么?operator new失败,还是构造函数失败?一,std::nothrow_t类型的new,可以不抛异常,返回值为0表示,也可以看出标准制订者也看不出有不使用异常的需要,二 构造函数中最好不要抛异常,构造函数出现异常,则不会调用析构函数,直接调用operator delete删除内存,则构造函数本身要负责初始化一半的那些结构的清理工作,导致函数责任混乱,恰当的做法是为那些私有属性初始化会发生失败的操作单独放在一个init()方法中。
re: 08年07月16日[未登录] CppExplore 2008-07-17 20:05
@RichardHe
我猜也是你拿到返回的数据很困难,呵呵。
用socket吧 不需要用apache ace libevent那么复杂的封装库。写个最基本最简单的阻塞式socket,连接 发送 ,等响应,之后关闭就是了。发送就是发送这个好了:
POST /url HTTP/1.1\r\n
Content-Length: 24\r\n
Content-Type: application/txt\r\n
\r\n
username=jim&pass=mypass
详细的信息可以问那边要,他们一定有示例的页面,用页面发个请求,抓包就知道了。
re: 08年07月16日[未登录] cppexplore 2008-07-17 17:20
@RichardHe
web也是用的socket。http的通讯方式如下:
建立连接(connect)
发送请求(send)
接收响应(recv)
断开连接(close)
每次请求响应 都要建立连接,断开连接,就是tcp短连接,也是http使用的方式。
http的格式可以看rfc,或者抓包看看就知道
一般是(post方式才需要body的):
post/get/header url http/1.1\r\n
header: value\r\n
Content-Length: ..\r\n
Content-Type: ..\r\n
\r\n
body
内嵌web可以说是个很快速的方案,只要你能拿到web上返回的数据,又何必自己写socket发数据呢。或者可以一边用内嵌web写原型系统,一边写socket方式的。
re: 08年07月16日[未登录] cppexplore 2008-07-17 13:01
@ 代李
可以
这对博主来说是个好方案,还是用socket发送,可以建立tcp短连接,发送的数据采用http协议格式的,这样就两边皆大欢喜了吧。
re: 08年07月16日[未登录] cppexplore 2008-07-17 12:18
根本原因还是因为那边没有socket,想直接用servlet吧。这样他们那边的改动很小,不需要涉入他们不熟悉的领域。被hook,指键盘输入吗,web下一样可以。单纯的得出结论:web输入比client端输入更安全,这个论调还需要详细的论证吧,用客户端的东东多了去了,也都没用客户端嵌入web的方式输密码。
https可以用ssl加密隧道,socket一样可以。
这个问题就是要么你们改,他们不改,要么他们不改,你们用web输入。
衡量2个方案的改动量,还是你们改比较简单。
re: 08年07月16日[未登录] cppexplore 2008-07-17 08:41
他们的server端是java之类的东西写的吧。
他们不会或者懒得写socket,想直接用servelet而已
re: 关于子进程和父进程--fork函数[未登录] cppexplore 2008-07-08 11:47
系统全面的看下
要不 今天发现了fork 很惊奇感慨
明天又发现了pthread_cond,又很惊奇感慨
某天又发现了pthread_testcancel,又很惊奇感慨
某天天又发现了还有惊群的说法,再来感慨。
不如直接浏览下apue unp之类的书,全面的看下。
博主还是很有专研精神的,把握好大方向,基础打坚实,.......
re: 关于子进程和父进程--fork函数 cppexplore 2008-07-07 12:53
唉 深入学习前 先多看看基础的书
re: C++中如何获得系统毫秒数 cppexplore 2008-07-06 20:39
linux上都是用gettimeofday
win上还是ftime,一般为了跨平台,win上会实现gettimeofday,如下:
int inline gettimeofday (struct timeval *tp, void *tz)
{
struct _timeb timebuffer;
_ftime (&timebuffer);
tp->tv_sec = timebuffer.time;
tp->tv_usec = timebuffer.millitm * 1000;
return 0;
}
开源都是*inux友好的,tgz是linux下的常见压缩包。tar zvxf .tgz解压。
and removed!
re: Epoll笔记![未登录] cppexplore 2008-06-24 11:32
没觉得有什么必要性,每个socket都有自己的缓存的,不是共用的,再引入的复杂性和产出之间权衡下。网络层上接线程消息队列,属于系统线程划分的范畴,不仅epoll可以 select、poll等每个都可以。
完全与iocp相同,自己封装就可,仅仅是外在的表现形式,并不是穿了一件AIO的外衣 就有AIO的性能。
re: C++随笔分类列表(基础)[未登录] cppexplore 2008-06-24 09:19
@梦在天涯
哈哈,暴露了。我给他开玩笑呢。学生时代不好好学习,不思进取,不对,但也有很多变通的方法,明天下午递交,前天晚上抱佛脚,这个错误太严重,更严重的是没有找到变通的正确方法,老以为不通过任何的努力,天上就能掉馅饼,还能咬上一口。
re: Epoll笔记![未登录] CppExplore 2008-06-23 12:25
socket本身有发送缓冲区的,不必再关联写数据队列或缓存。不放心可以开大缓冲区。
@free2000fly
不好意思 原来是是连续的 呵呵
描述的太简单太简单了 看了之后难以跟进重现啊
放首页,炫耀意义大于借鉴意义
re: 【原创】技术系列之 网络模型(二)[未登录] CppExplore 2008-06-19 13:26
@Jeff
udp也可以啊,模型简单,在一个端口上复用就可以了,没什么可写的。
re: 服务器设计,开发的体会 cppexplore 2008-06-14 11:00
顶下!
re: SGI STL的内存池[未登录] CppExplore 2008-06-12 22:52
唉 水已经满了 会错过很多东西的
re: std::queue的front的问题[未登录] cppexplore 2008-06-10 12:39
value_type& front( );
只是说明返回的时候,不copy副本返回,直接返回私有属性本身。
比如:
class A
{
public:
A():a_(9){}
const int & get_a()const{return a_;}
private:
int a_;
};
int main()
{
A a;
printf("it's %d\n",a.get_a()+4);
return 0;
}
a.get_a()+4这个其实就是a_+4,而不设计到内存copy问题。如果get_a()前没有引用,则意味着先要把a_复制一副本,副本再和4相加。
该文中,int head=则是赋值操作,和后面的是否是引用无关,基本类型,当然会有效。
re: (C++)一个愚蠢的错误[未登录] CppExplore 2008-06-06 22:00
晕倒
chinaunix上的是你哦,我是voipexplore。string内存布局不透明,只能用new类,不能用malloc类。
另楼上 包含string.h 是为了用memset
re: 写了一个弹性物体碰撞模拟[未登录] cppexplore 2008-06-06 12:05
呵呵 我要表达的主要意思在后半句。
re: 写了一个弹性物体碰撞模拟[未登录] cppexplore 2008-06-06 11:46
“等程序改好了之后再把代码弄出来”??
呵呵 最好改好的时候把思路 主要难题 代码放到首页。本文这种放首页就没什么意义,授人以鱼,不如授人以渔。
放在首页的时候 能不能考虑下 文章是不是有一定的原创性 能不能让看的人有点收获
系统常用命令、vim常用命令都很有用处 为何不从深度、广度两方面着手整理下再发到首页呢
re: 关于系统设计 cppexplore 2008-06-06 08:43
呵呵 博主很坚持啊
re: 【原创】系统设计之 必备外围功能-log cppexplore 2008-06-05 19:44
呵呵 以为我的log框架你会喜欢,看来我错了。不过还有一句话“如果你没使用过log4cplus,ok,那么下载一个log4cplus,编译,......,尝试以下,你一定会惊叹log4cplus的强大与美妙。”
还没接触过语音板卡 我们的应用没有媒体编解码或者dtmf检测的。有时间向你讨教讨教,留个联系方式吧,我的gtalk/gmail是gamil.com的,msn是live.com的,名称都是zongjinliang。
@true
呵呵 linux上的应用服务器 软交换服务器 流媒体服务器等。
re: 调查一下:你工作之余有没有赚外快?[未登录] cppexplore 2008-05-21 08:32
呵呵 兄弟拉到项目 找我合作啊 server端服务器协议开发 业务开发以及数据库到web无所不能啊
re: 关于epoll[未登录] cppexplore 2008-05-19 08:42
我测试的结果,两者没有明显的性能差异。
re: 做个投票,大家支持[未登录] cppexplore 2008-05-15 11:54
1、c 学生时代的唯一途径,数据结构也是考研的必考科目:结构和算法
2、c 编译原理的课程作业
3、a(学生时代),当时没研究过stl,更没听过boost
4、b(现在),更多的是封装实现模块,极少考虑基础的结构,纯c下freebsd的宏结构也都很不错。
linux/gcc/g++
re: FTP开发中下载文件的两种方式[未登录] cppexplore 2008-05-14 08:56
第一个信令端口超时了 一定间隔内发点命令过去就好
最后下载结束的时候 会检测信令端口是否超时的