<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>eYou开发者</title>
	<atom:link href="http://team.eyou.com/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://team.eyou.com</link>
	<description></description>
	<lastBuildDate>Fri, 03 Sep 2010 06:39:37 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>solaris上报libintl_textdomain未定义的解决办法</title>
		<link>http://team.eyou.com/?p=37</link>
		<comments>http://team.eyou.com/?p=37#comments</comments>
		<pubDate>Fri, 03 Sep 2010 06:39:37 +0000</pubDate>
		<dc:creator>cress</dc:creator>
				<category><![CDATA[闲七杂八]]></category>

		<guid isPermaLink="false">http://team.eyou.com/?p=37</guid>
		<description><![CDATA[今天编译一个程序，里面用到textdomain函数，Makefile里加进去了-lgettextlib，并且gcc时也找到了这个库，但是始终报
libintl_textdomain未定义，操作系统solaris 10，后来google找到了解决办法：在Makefile中增加-lintl的依赖，问题解决了。
]]></description>
		<wfw:commentRss>http://team.eyou.com/?feed=rss2&amp;p=37</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Libevent：evbuffer缓冲区分析</title>
		<link>http://team.eyou.com/?p=32</link>
		<comments>http://team.eyou.com/?p=32#comments</comments>
		<pubDate>Thu, 05 Aug 2010 08:34:34 +0000</pubDate>
		<dc:creator>zhanghua</dc:creator>
				<category><![CDATA[闲七杂八]]></category>

		<guid isPermaLink="false">http://team.eyou.com/?p=32</guid>
		<description><![CDATA[Libevent：evbuffer缓冲区分析
在开发网络程序的时候，特别是TCP基于字节流的数据，需要从字节流数据中解析出自己的通讯协议，比如读一行数据：我们每次调用read函数的时候指定了我们期望读多少数据，但这个数据并不一定正好能读到‘\n’，这个时候就需要借助一个缓冲区来保存多余的数据，以便于和下一次读到的数据合并在一起继续分析。Evbuffer就是提供了这样一个缓冲区。

关于libevent的缓冲模块，主要就是围绕evbuffer结构体展开。先看下evbuffer的定义：



struct evbuffer{
// 当前有效缓冲区的内存起始地址
u_char *buffer;
// 整个分配(realloc)用来缓冲的内存起始地址
u_char *orig_buffer;
// origin_buffer和buffer之间的字节数
size_t misalign;
// 整个分配用来缓冲的内存字节数
size_t totallen;
// 当前有效缓冲区的长度(字节数)
size_t off;
//回到函数，当缓冲区有变化的时候会被调用
void (*cb)(struct evbuffer *, size_t, size_t, void *);
//回调函数的参数
void *cbarg;
};



下面简单介绍一下evbuffer提供的 API，我所使用的libevent版本是1.4.10-stable:



struct evbuffer* evbuffer_new(void)



动态分配一个struct evbuffer结构，需要调用evbuffer_free释放内存。



void evbuffer_free(struct evbuffer *buffer)



释放buffer所占用的内存。



int evbuffer_add(struct evbuffer *buf, const void *data, size_t datlen)



将data追加到evbuffer中
先判断缓冲区的大小是否可以容纳的下datlen大小， 如果不能，则使用evbuffer_expand扩充容量。然后将data追加到evbuffer-&#62;buffer + evbuffer-&#62;off后。 并且更新有效缓冲区长度off。
如果datlen &#62; 0， 并且设置了回调函数，则调用回调函数
返回值：成功返回0，失败返回-1。



int evbuffer_add_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf)



移动数据从一个evbuffer到另一个evbuffer。
实际上还是调用了evbuffer_add添加数据到outbuf中。但会清除inbuf中的数据。
返回值：成功返回0， 失败返回-1。



int evbuffer_add_printf( struct evbuffer *, const char* fmt, ...)



添加一个格式化的字符串到evbuffer尾部。



int evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap)



添加一个va_list格式的字符串到evbuffer尾部。



void evbuffer_drain(struct evbuffer *buf, size_t len)



从evbuffer起始位置删除指定长度len字节数据
如果len的长度大于等于缓冲区的off的长度，则表明缓冲区的数据都被清空。
如果缓冲区发生变化，并且设置了回调函数，则调用回调函数。



int evbuffer_expand(struct evbuffer *buf, size_t datlen)



该函数用于扩充evbuffer的容量。每次向evbuffer写数据时，都是将数据写到buffer+off后，buffer到buffer+off之间已被使用，保存的是有效数据，而orig_buffer和buffer之间则是因为读取数据移动指针而形成的无效区域。
evbuffer_expand的扩充策略在于：
1，计算出加上datlen后需要的缓冲区大小need
2, 判断当前缓冲区的长度是否可以容纳的下need大小，如果可以则不需要改变缓冲区的大小，直接返回。
3，如果当前缓冲哦你去的长度容纳不下need大小，则判断orig_buffer和buffer之间的空闲区域是否可以容纳添加的数据，如果
可以，则移动buffer和buffer+off之间的数据到orig_buffer和orig_buffer+off之间，然后把新的数据拷贝到orig_buffer+off之后；
4，如果misalign不可以容纳，那么重新分配更大的空间(realloc)，同样会移动数据。
扩充内存的策略为：确保新的内存区域最小尺寸为256，且以乘以2的方式逐步扩大(256、512、1024、&#8230;)。
返回值：成功返回0， 失败返回-1。



u_char *evbuffer_find(struct evbuffer *buffer, const u_char *what, size_tlen)



查找缓冲区中是否存在指定的字符串what。
注意这里使用的是u_char类型，说明有可能查找的数据不是以’’结尾
如果存在返回指向字符串what的指针，没有则返回NULL。



int evbuffer_read(struct evbuffer *buf, int fd, int howmuch)



调用read/recv函数，从文件描述符fd上读取数据到evbuffer中。如果缓冲区不够，调用evbuffer_expand扩充缓冲区。



int evbuffer_write(struct evbuffer *buffer, int fd)



把缓冲区中的数据，调用send/write函数写入文件描述符fd上， 如果send/write函数写入的字节数大于0，则调用evbuffer_drain删除已写的数据。



char *evbuffer_readline(struct evbuffer *buffer)



读取数据以&#8221;\r\n&#8221;,&#8221;\n\r&#8221;, &#8220;\r&#8221; 或者 &#8221;\n&#8221;结尾。
返回动态分配内存，需要调用者自己使用free来释放内存。返回一个以“”结尾的字符串。



int evbuffer_remove(struct evbuffer *buf, void *data, size_t datlen)



将evbuffer缓冲区中的数据读到data中， 最多读datlen字节。如果缓冲区里的数据小于datlen，则拷贝缓冲区中全部数据。
然后调用evbuffer_drain删除已读数据。



void evbuffer_setcb(struct evbuffer *buffer,
void (*cb)(struct evbuffer *, size_t, size_t, void *),
void *cbarg)




设置回调函数。当缓冲区中发生变化时， 调用设置的回调函数。
Evbuffer提供的API已经全部介绍完毕，接下来我们通过一个实例进一步学习如何使用evbuffer, 想要使用evbuffer，系统里必须已经安装了libevent。
例子代码如下：evbuffer-test.c



 1 #include &#60;stdio.h&#62;
2 #include &#60;string.h&#62;
3 #include &#60;assert.h&#62;
4
5 //引入libevent头文件
6 #include "event.h"
7
8 int main(int argc, char** argv)
9 {
10     struct evbuffer* buff = NULL;
11     char c, c2[3] = {0};
12
13     buff = evbuffer_new();
14     assert(buff != NULL);
15
16     evbuffer_add(buff, "1", 1);
17     evbuffer_add(buff, "2", 1);
18     evbuffer_add(buff, "3", 1);
19     evbuffer_add_printf(buff, "%d%d", 4, 5);
20     assert(buff-&#62;off == 5);
21
22     evbuffer_remove(buff, &#38;c, sizeof(char));
23     assert(c == '1');
24     evbuffer_remove(buff, &#38;c, sizeof(char));
25     assert(c == '2');
26   [...]]]></description>
		<wfw:commentRss>http://team.eyou.com/?feed=rss2&amp;p=32</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>浅析Linux下core文件</title>
		<link>http://team.eyou.com/?p=27</link>
		<comments>http://team.eyou.com/?p=27#comments</comments>
		<pubDate>Thu, 22 Jul 2010 09:26:37 +0000</pubDate>
		<dc:creator>zhanghua</dc:creator>
				<category><![CDATA[闲七杂八]]></category>

		<guid isPermaLink="false">http://team.eyou.com/?p=27</guid>
		<description><![CDATA[张华 (zhanghua@eyou.net)
2006 年 8 月 02 日

当我们的程序崩溃时，内核有可能把该程序当前内存映射到core文件里，方便程序员找到程序出现问题的地方。最常出现的，几乎所有C程序员都出现过的错误就是“段错误”了。也是最难查出问题原因的一个错误。下面我们就针对“段错误”来分析core文件的产生、以及我们如何利用core文件找到出现崩溃的地方。
何谓core文件

当一个程序崩溃时，在进程当前工作目录的core文件中复制了该进程的存储图像。core文件仅仅是一个内存映象(同时加上调试信息)，主要是用来调试的。
当程序接收到以下UNIX信号会产生core文件：



名字
说明
ANSI C POSIX.1
SVR4 4.3+BSD
缺省动作


SIGABRT
异常终止(abort)
.       .
.      .
终止w/core


SIGBUS
硬件故障
.
.      .
终止w/core


SIGEMT
硬件故障

.      .
终止w/core


SIGFPE
算术异常
.       .
.      .
终止w/core


SIGILL
非法硬件指令
.       .
.      .
终止w/core


SIGIOT
硬件故障

.      .
终止w/core


SIGQUIT
终端退出符
.
.      .
终止w/core


SIGSEGV
无效存储访问
.       .
.      .
终止w/core


SIGSYS
无效系统调用

.      .
终止w/core


SIGTRAP
硬件故障

.      .
终止w/core


SIGXCPU
超过CPU限制(setrlimit)

.      .
终止w/core


SIGXFSZ
超过文件长度限制(setrlimit)

.      .
终止w/core



在系统默认动作列，“终止w/core”表示在进程当前工作目录的core文件中复制了该进程的存储图像（该文件名为core，由此可以看出这种功能很久之前就是UNIX功能的一部分）。大多数UNIX调试程序都使用core文件以检查进程在终止时的状态。
core文件的产生不是POSIX.1所属部分,而是很多UNIX版本的实现特征。UNIX第6版没有检查条件(a)和(b)，并且其源代码中包含如下说明：“如果你正在找寻保护信号，那么当设置-用户-ID命令执行时，将可能产生大量的这种信号”。4.3 + BSD产生名为core.prog的文件，其中prog是被执行的程序名的前1 6个字符。它对core文件给予了某种标识，所以是一种改进特征。
表中“硬件故障”对应于实现定义的硬件故障。这些名字中有很多取自UNIX早先在DP-11上的实现。请查看你所使用的系统的手册，以确切地确定这些信号对应于哪些错误类型。
下面比较详细地说明这些信号。
• SIGABRT 调用abort函数时产生此信号。进程异常终止。
• SIGBUS 指示一个实现定义的硬件故障。
• SIGEMT 指示一个实现定义的硬件故障。
EMT这一名字来自PDP-11的emulator trap 指令。
• SIGFPE 此信号表示一个算术运算异常，例如除以0，浮点溢出等。
• SIGILL 此信号指示进程已执行一条非法硬件指令。
4.3BSD由abort函数产生此信号。SIGABRT现在被用于此。
• SIGIOT 这指示一个实现定义的硬件故障。
IOT这个名字来自于PDP-11对于输入／输出TRAP(input/output TRAP)指令的缩写。系统V的早期版本，由abort函数产生此信号。SIGABRT现在被用于此。
• SIGQUIT 当用户在终端上按退出键（一般采用Ctrl-\）时，产生此信号，并送至前台进
程组中的所有进程。此信号不仅终止前台进程组（如SIGINT所做的那样），同时产生一个core文件。
• SIGSEGV 指示进程进行了一次无效的存储访问。
名字SEGV表示“段违例（segmentation violation）”。
• SIGSYS 指示一个无效的系统调用。由于某种未知原因，进程执行了一条系统调用指令，
但其指示系统调用类型的参数却是无效的。
• SIGTRAP 指示一个实现定义的硬件故障。
此信号名来自于PDP-11的TRAP指令。
• SIGXCPU SVR4和4.3+BSD支持资源限制的概念。如果进程超过了其软C P U时间限制，则产生此信号。
• SIGXFSZ 如果进程超过了其软文件长度限制，则SVR4和4.3+BSD产生此信号。
摘自《UNIX环境高级编程》第10章 信号。
使用core文件调试程序 
看下面的例子：
/*core_dump_test.c*/
1 #include &#60;stdio.h&#62;
2
3 const char *str = &#8220;test&#8221;;
4
5 void core_test()
6 {
7     str[1] = &#8216;T&#8217;;
8 }
9
10 int main()
11 {
12     core_test();
13
14     return 0;
15 }
编译：
[zhanghua@localhost core_dump]$ gcc –g core_dump_test.c -o core_dump_test
如果需要调试程序的话，使用gcc编译时加上-g选项，这样调试core文件的时候比较容易找到错误的地方。
执行：
[zhanghua@localhost core_dump]$ [...]]]></description>
		<wfw:commentRss>http://team.eyou.com/?feed=rss2&amp;p=27</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>嘻嘻</title>
		<link>http://team.eyou.com/?p=21</link>
		<comments>http://team.eyou.com/?p=21#comments</comments>
		<pubDate>Mon, 19 Jul 2010 09:59:21 +0000</pubDate>
		<dc:creator>nn</dc:creator>
				<category><![CDATA[闲七杂八]]></category>

		<guid isPermaLink="false">http://team.eyou.com/?p=21</guid>
		<description><![CDATA[没有其他表情吗！！！~
]]></description>
		<wfw:commentRss>http://team.eyou.com/?feed=rss2&amp;p=21</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>RFC3501（imp4协议）——RFC3501协议的英文翻译</title>
		<link>http://team.eyou.com/?p=18</link>
		<comments>http://team.eyou.com/?p=18#comments</comments>
		<pubDate>Mon, 19 Jul 2010 09:52:01 +0000</pubDate>
		<dc:creator>liujun</dc:creator>
				<category><![CDATA[闲七杂八]]></category>

		<guid isPermaLink="false">http://team.eyou.com/?p=18</guid>
		<description><![CDATA[因特网邮件访问协议，版本4rev1（IMAP4rev1）允许一个客户端访问和操作在一个服务器上的电子邮件。IMAP4rev1允许，以一种功能上等效于本地文件夹的方式，操作邮箱（远程邮件文件夹）。IMAP4rev1也提供这样一个功能，一个离线客户端与服务器异步（交互）。

IMAP4rev1包括以下操作：创建、删除、及重命名邮箱，检查新邮件，永久删除邮件，设置和清除标记，RFC2822及RFC2045解析，检索，及选择性的获取邮件属性，文本，及其中的一部分。IMAP4rev1中的邮件通过使用数字访问。这些数字或者是邮件序列号，或者是唯一标识符。
IMAP4rev1支持单个服务器。访问注册信息以支持多个IMAP4rev1服务器的机制在RFC2244中讨论。
IMAP4rev1不详述邮递邮件的方法；该职责由如RFC2821的某种邮件传输协议完成。
目录
１.　如何阅读本文 5
１.1.　本文的结构 5
1.2 本文用到的约定语 5
1.3. 实现者需要特别注意的地方 6
2. 协议概述 6
2.1. 链路层 6
2.2. 命令及响应 6
2.2.1. 客户端的协议发送和服务器端的协议接收 7
2.2.2. 服务器端的协议发送和客户端的协议接收 7
2.3. 邮件属性 8
2.3.1. 邮件号 8
2.3.1.1. 唯一标识符（UID）的邮件属性 8
2.3.1.2. 邮件序列号的邮件属性 9
2.3.2. 标记的邮件属性 9
2.3.3. 实际日期的邮件属性 11
2.3.4. [RFC-2822]大小的邮件属性 11
2.3.5. 信封结构的邮件属性 11
2.3.6. 主体结构的邮件属性 11
2.4. 邮件文本 11
3. 状态和流程图 11
3.1. 未认证状态 12
3.2. 认证状态 12
3.3. 选中状态 12
3.4. 注销状态 12
4. 数据格式 14
4.1. 原语 14
4.2. 数字 14
4.3. 字符串 14
4.3.1. 字节及二进制字符串 14
4.4. 圆括符列表 15
4.5. NIL  15
5. 操作的考虑 15
5.1. 邮箱命名 15
5.1.1. 邮箱层级命名 16
5.1.2. 邮箱命名空间的约定 16
5.1.3. 邮箱的国际命名约定 16
5.2. 邮箱大小和邮件状态更新 17
5.3. 没有命令在行进中的响应 18
5.4. 自动注销计时器 18
5.5. 多个命令在行进中 18
6. 客户端命令 19
6.1. 客户端命令－任意状态 19
6.1.1. CAPABILITY命令 20
6.1.2. NOOP命令 20
6.1.3. LOGOUT命令 21
6.2. 客户端命令－未认证状态 21
6.2.1. STARTTLS命令 22
6.2.2. AUTHENTICATE命令 23
6.2.3. LOGIN 命令 25
6.3. 客户端命令－认证状态 25
6.3.1. SEELCT命令 25
6.3.2. EXAMINE命令 [...]]]></description>
		<wfw:commentRss>http://team.eyou.com/?feed=rss2&amp;p=18</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>螃蟹表情</title>
		<link>http://team.eyou.com/?p=16</link>
		<comments>http://team.eyou.com/?p=16#comments</comments>
		<pubDate>Mon, 19 Jul 2010 09:50:33 +0000</pubDate>
		<dc:creator>uusky</dc:creator>
				<category><![CDATA[闲七杂八]]></category>
		<category><![CDATA[测试]]></category>

		<guid isPermaLink="false">http://team.eyou.com/?p=16</guid>
		<description><![CDATA[~\(≧▽≦)/~
]]></description>
		<wfw:commentRss>http://team.eyou.com/?feed=rss2&amp;p=16</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>测试</title>
		<link>http://team.eyou.com/?p=13</link>
		<comments>http://team.eyou.com/?p=13#comments</comments>
		<pubDate>Mon, 19 Jul 2010 09:41:39 +0000</pubDate>
		<dc:creator>cress</dc:creator>
				<category><![CDATA[闲七杂八]]></category>

		<guid isPermaLink="false">http://team.eyou.com/?p=13</guid>
		<description><![CDATA[测试
]]></description>
		<wfw:commentRss>http://team.eyou.com/?feed=rss2&amp;p=13</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Hello world!</title>
		<link>http://team.eyou.com/?p=1</link>
		<comments>http://team.eyou.com/?p=1#comments</comments>
		<pubDate>Wed, 26 May 2010 06:00:21 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[闲七杂八]]></category>

		<guid isPermaLink="false">http://team.eyou.com/?p=1</guid>
		<description><![CDATA[Welcome to WordPress. This is your first post. Edit or delete it, then start blogging!
]]></description>
		<wfw:commentRss>http://team.eyou.com/?feed=rss2&amp;p=1</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
