The difference between blocking and nonblocking network programming in the socket (linux)

读操作

对于阻塞的socket,当socket的接收缓冲区中没有数据时,read调用会一直阻塞住,直到有数据到来才返

回。当socket缓冲区中的数据量小于期望读取的数据量时,返回实际读取的字节数。当sockt的接收缓冲

区中的数据大于期望读取的字节数时,读取期望读取的字节数,返回实际读取的长度。

对于非阻塞socket而言,socket的接收缓冲区中有没有数据,read调用都会立刻返回。接收缓冲区中有
数据时,与阻塞socket有数据的情况是一样的,如果接收缓冲区中没有数据,则返回错误号为

EWOULDBLOCK,
表示该操作本来应该阻塞的,但是由于本socket为非阻塞的socket,因此立刻返回,遇到这样的情况,可

以在下次接着去尝试读取。如果返回值是其它负值,则表明读取错误。
因此,非阻塞的rea调用一般这样写:

if ((nread = read(sock_fd, buffer, len)) < 0)
{
if (errno == EWOULDBLOCK)
{
return 0; //表示没有读到数据
}else return -1; //表示读取失败
}else return nread;读到数据长度

写操作

对于写操作write,原理是类似的,非阻塞socket在发送缓冲区没有空间时会直接返回错误号EWOULDBLOCK,
表示没有空间可写数据,如果错误号是别的值,则表明发送失败。如果发送缓冲区中有足够空间或者
是不足以拷贝所有待发送数据的空间的话,则拷贝前面N个能够容纳的数据,返回实际拷贝的字节数。

而对于阻塞Socket而言,如果发送缓冲区没有空间或者空间不足的话,write操作会直接阻塞住,如果有

足够空间,则拷贝所有数据到发送缓冲区,然后返回.
非阻塞的write操作一般写法是:

int write_pos = 0;
int nLeft = nLen;

while (nLeft > 0)
{
int nWrite = 0;
if ((nWrite = write(sock_fd, data + write_pos, nLeft)) <= 0)
{
if (errno == EWOULDBLOCK)
{
nWrite = 0;
}else return -1; //表示写失败
}
nLeft -= nWrite;
write_pos += nWrite;
}
return nLen;

建立连接
阻塞方式下,connect首先发送SYN请求道服务器,当客户端收到服务器返回的SYN的确认时,则

connect
返回.否则的话一直阻塞.
非阻塞方式,connect将启用TCP协议的三次握手,但是connect函数并不等待连接建立好才返回,而是
立即返回。返回的错误码为EINPROGRESS,表示正在进行某种过程.

接收连接
对于阻塞方式的倾听socket,accept在连接队列中没有建立好的连接时将阻塞,直到有可用的连接,才返

回。
非阻塞倾听socket,在有没有连接时都立即返回,没有连接时,返回的错误码为EWOULDBLOCK,表示本来应
该阻塞。
无阻塞的设置方法

方法一:fcntl
int flag;
if (flag = fcntl(fd, F_GETFL, 0) <0) perror(“get flag”);
flag |= O_NONBLOCK;
if (fcntl(fd, F_SETFL, flag) < 0)
perror(“set flag”);

方法二:ioctl

int b_on = 1;
ioctl (fd, FIONBIO, &b_on);

c++模拟实现类名反射

[codesyntax lang=”c”]

[/codesyntax]

how to invoke exe silently

[codesyntax lang=”cpp”]

[/codesyntax]

how to delete directory using windows API

[codesyntax lang=”cpp”]

[/codesyntax]

X509 in OpenSSL

OpenSSL之X509系列之1—引言和X509概述


【引言】
X509是系列的函数在我们开发与PKI相关的应用的时候我们都会用到,但是OpenSSL中对X509的描述并不是很多,鉴于些,我将以前工作与学习过程的经验整理出来,供大家参考,不用多走弯路,可以将精力集中在自己要处理的业务逻辑上,同时也希望更多的人参与到研究与整理信息安全的理论与技术中来,提高中国的科研与应用技术水平。提高中国信息安全意识与能力从我做起。
【X509概述】
X.509是国际标准化组织CCITT建议作为X.500目录检索的一部分提供安全目录检索服务。一份X.509证书是一些标准字段的集合,这些字段包含有关用户或设备及其相应公钥的信息一种非常通用的证书格式,所有的证书都符合X.509 国际标准。目前X.509有不同的版本,例如 X.509 V2和x.509 v3都是目前比较新的版本,2000年还推出V4版本,但是都在原有版本基础上进行功能的扩充,其中每一版本必须包含下列信息:
(1) 用来区分X.509的不同版本号既版本号
(2) 由CA给予每一个证书的分配的编号即序列号;
(3) 用于产生证书所用的方法以及一切参数即签名算法
(4) CA的x.500名字即发出该证书的认证机构
(5) 证书有效的时间包括两个日期,在所指定的两个时间之 间有效即有效期限
(6) 证书持有人的姓名、服务处所等信息即主题信息
(7) 认证机构的数字签名
(8) 被证明的公钥值,加上使用这个公钥的方法名称即公钥信息
【X.509证书格式】
X.509是另一种非常通用的证书格式。所有的证书都符合ITU-T X.509国际标准;因此(理论上)为一种应用创建的证书可以用于任何其他符合X.509标准的应用。但实际上,不同的公司对X.509证书进行了不同的扩展,不是所有的证书都彼此兼容。在一份证书中,必须证明公钥及其所有者的姓名是一致的。对PGP证书来说,任何人都可以扮演认证者的角色。对X.509证书来说,认证者总是 CA或由CA指定的人(其实PGP证书也完全支持使用CA来确认证书的体系结构),一份X.509证书是一些标准字段的集合,这些字段包含有关用户或设备及其相应公钥的信息。X.509标准定义了证书中应该包含哪些信息,并描述了这些信息是如何编码的(即数据格式),所有的X.509证书包含以下数据:
(1)X.509版本号:指出该证书使用了哪种版本的X.509标准,版本号会影响证书中的一些特定信息。目前的版本是3。
(2)证书持有人的公钥:包括证书持有人的公钥,算法(指明密钥属于哪种密码系统)的标示符和其他相关的密钥参数。
(3)证书的序列号:创建证书的实体(组织或个人)有责任为该证书指定一个独一无二的序列号,以区别于该实体发布的其他证书。序列号信息有许多用途;比如当一份证书被回收以后,它的序列号就被放入证书回收列表(CRL)之中。
(4)证书持有人唯一的标示符:(或称DN-distinguished name)这个名字在 Internet上应该是唯一的。DN由许多部分组成,看起来象这样:
CN=Bob Allen, OU=Total Network Security Division,
O=Network Associates, Inc., C=US
这些信息指出该科目的通用名,组织单位,组织和国家
(5)证书的有效期:证书起始日期和时间以及终止日期和时间;指明证书何时失效。
(6)证书发布者的唯一名字:这是签发该证书的实体的唯一名字。通常是CA。.使用该证书意味着信任签发证书的实体。(注意:在某些情况下,比如根或顶级CA证书,发布者自己签发证书)
(7)发布者的数字签名:这是使用发布者私钥生成的签名。
(8)签名算法的标示符:指明CA签署证书所使用的算法。
X.509证书和PGP证书之间有许多不同,最明显的如下所述:
(1) 用户可以创建自己的PGP证书,但是必须向CA请求才能得到一份X.509证书。
(2)X.509证书天生只支持密钥拥有者的一个名字。
(3)X.509证书只支持证明密钥合法性的一个数字签名。
要获得一份X.509证书,必须请求CA发给你证书。用户提供自己的公钥,证明自己拥有相应的私钥,并提供有关自己的某些特定信息。然后在这些信息上数字签名,并将整个数据包(称为证书请求)发给CA。CA做一些努力来验证用户提供的信息是正确的,然后就生成证书并返回给用户。
【OpenSSL对X509的支持】
以下是我自己对OpenSSL的理解,可以表达上不是很准确。
(1) 证书请求管理
(2) 证书生成
(3) 证书吊销及CRL管理
(4) X509名字管理
(5) 属性管理
(6) 扩展管理
(7) 验证及信任管理
在随后的一些篇幅中将对以上的这几个方面进行展开说明。

 

 

OpenSSL之X509系列之2—证书请求管理

【数据结构】
证书请求用到了两个重要的数据结构:证书请求信息结构X509_REQ_INFO与证书请求结构X509_REQ,二者的定义如下:

[codesyntax lang=”cpp”]

[/codesyntax]

其中version就是版本号、subject就是主题(常用的是dn)、pubkey是事先生成的公钥、attributes是一系列的属性,用于表达证书主题的额外信息,细节参见PKCS#10与PKCS#9。

[codesyntax lang=”cpp”]

[/codesyntax]

其中req_info就是上面所说的证书请求信息、sig_alg是签名使用的算法比如md5WithRSAEncryption、signature就是签名值了。
【基本操作函数概述】
这些基本的操作函数主要是对证书请求项进行设置与读取操作,它的的定义如下:其中的X509_REQ* req对数指的是要操作的X509_REQ对象,下面不再赘述。

[codesyntax lang=”cpp”]

[/codesyntax]

【X509_REQ_set_version】
设置版本号, version就是版本号。
【X509_REQ_set_subject_name】
该函数设置证书请求人的主题名,X509_NAME *name参数就是要设置的主题名。对于名字的操作到时会有一个专题来讲。
【X509_REQ_set_pubkey】
设置公钥,EVP_PKEY *pkey参数就是生成好的公钥,可以通过RSA_generate_key()来生成。
比如:

[codesyntax lang=”cpp”]

[/codesyntax]

 

【X509_REQ_get_pubkey】
读取X509_REQ中的公钥信息,返回的是一个EVP_PKEY对象,X509_REQ_extract_key()是它的一个宏定义,功能相同。
【X509_REQ_sign】
对X509_REQ中X509_REQ_INFO结构用pkey与md进行签名,并用算法标识与签名值填充X509_REQ中的sig_alg与signature域。
【X509_REQ_verify】
与签名相对应,对签名进行验证,所以将公钥pkey传入就可以了。

OpenSSL之X509系列之3—证书请求的IO函数

【输入输出函数】
这些函数有两类:一类是将X509_REQ信息在文件或BIO抽象层上输入输出,另一类是在控制台上将X509_REQ信息进行显示。它们的函数定义如下:

[codesyntax lang=”cpp”]

[/codesyntax]

【d2i_X509_REQ_fp】
将证书请求从文件中读入并转化成X509_REQ内部结构。
【i2d_X509_REQ_fp】
将X509_REQ对象进行DER编码输出,并写入fp指定的文件中。
【d2i_X509_REQ_bio】
功能与d2i_X509_REQ_fp相同,只是读的时候从BIO抽象层上读,你可以将它与文件相关联就可以了。
【i2d_X509_REQ_bio】
功能与i2d_X509_REQ_fp相同,只是写的时候从BIO抽象层上写,你可以将它与文件或者内存BIO相关联就可以输出了。
【X509_REQ_print】
将X509_REQ在BIO上输出,但输入是可以读的,比如Subject=XXX等。其实底层就是调用X509_REQ_print_ex来实现的。
【X509_REQ_print_ex】
这个函数与X509_REQ_print的区别是可以用标志去控制输出,nmflags用于控制显示方式,cflag用于控制哪些不显示,可以按自己的需要进行定制。它们的定义在x509.h里。
具体如下:

[codesyntax lang=”cpp”]

[/codesyntax]

【X509_REQ_print_fp】
其实这个函数就是将可读的结果保存在文件里,内存就是生成一个BIO对象BIO_new(BIO_s_file(),然后再将文件句柄传给他BIO_set_fp(b,fp,BIO_NOCLOSE),再调用X509_REQ_print函数进行输出。这几个print函数,具体实现在crypto/asn1/t_req.c中。

OpenSSL之X509系列之4—证书请求的扩展项操作
【扩展项操作函数】
这些函数主要是对证书的请求的扩展项进行读取与设置操作,

[codesyntax lang=”cpp”]

[/codesyntax]

【X509_REQ_extension_nid】
判断nid是否已经在内部nid_list列表中定义了。未定义返回0,否则返回1。
【X509_REQ_get_extension_nids】
返回已经定义的nid列表。
【X509_REQ_set_extension_nids】
设置定义好的nid列表。
【X509_REQ_get_extensions】
取出证书请求中的扩展项,过程是这样的,先从属性中将经过der编码的扩展项取出来,然后调用d2i_ASN1_SET_OF_X509_EXTENSION函数,将它转化成内部结构。
【X509_REQ_add_extensions】
将定义好,且赋了值的X509_EXTENSION扩展项加入证书请求中(其实是加到属性中,这在以后讲)。
【X509_REQ_add_extensions_nid】
功能与X509_REQ_add_extensions相同,只不过nid参数可以使用非标准的nid,其实X509_REQ_add_extensions就是通过调用这个函数是实现的,只不过使用了objects.h中定义的Extension Request标准定义。

[codesyntax lang=”cpp”]

#define NID_ext_req 172

[/codesyntax]

 

OpenSSL之X509系列之5—证书请求的其它相关操作

【相关操作函数】

[codesyntax lang=”cpp”]

[/codesyntax]

【X509_to_X509_REQ】
用X509证书结构直接生成一个证书请求结构,其中x就是证书结构,pkey是公钥,md是散列算法,操作的过程就是将证书里的主题名与公钥填充到X509_REQ证书请求结构中,然后用指定的pkey与md进行签名,成功返回X509_REQ证书请求结构。
【X509_REQ_to_X509】
从证书请求结构直接生成一个X509证书,其中的day就是证书的有效期(多少天),pkey就是用于签名的私钥。操作过程:从证书请求结构取出主题,将它填充到X509的主题与签发者中,取出公钥填充到X509公钥域里,有MD5与私钥进行签名,所以这样生成证书应用是一张自签名的证书。
【X509_REQ_digest】
将X509_REQ用指定的散列算法type进行散列。结果在md中,len是结果的长度。
【X509_REQ_dup】
复制一份X509_REQ结构。它是宏定义,实际上是由ASN1_dup函数来完成复制工作。

 

How to generate X509 req in c/c++ using openssl lib

要点:

// 1. generate rsa key
// 2. set version of x509 req
// 3. set subject of x509 req
// 4. set public key of x509 req
// 5. set sign key of x509 req
// 6. free

 

[codesyntax lang=”php”]

[/codesyntax]

how to compile pidgin?

I try to compile pidgin in mingw, but failed. there are two reasons:

a) the gcc version in msys is 3.4.4 (must be >=3.8)
b)the gcc version in mingw cannot find sys/socket.h

so I compile pidgin with cygwin.

 

 

2.1  http://cygwin.com/下载setup.exe f:/Cygwin目录下 

2.2  运行setup.exe 选择【下载不安装】下载(http://kambing.vlsm.org)安装包到f:/Cygwin目录下。安装包:bzip2,coreutils,gawk,grep,gzip,make,patch,sed,monotone,tar,unzip andwget (除了粗体字外其他包是默认选择)。

2.3  安装Cygwin:运行setup.exe 选择【从本地目录安装】下一步,选择根目录C:/Cygwin和本地包目录: F:/Cygwin

2.4  运行Cygwin。运行界面会提示你是第一次运行Cygwin 并自动设置home环境变量目录C:/cygwin/home.(注意home环境变量中不要包含空格或中文字符要不然会给你后面的工作带来麻烦,如果home环境变量已经被设置为C:/Documents and Settings,可以在我的电脑/属性/高级/环境变量删除home环境变量。从新启动Cygwin。另外我相信Cygwin 也有设置环境变量的命令)

2.5  输入命令 “wget http://gaim-extprefs.sf.net/winpidgin-build-fetcher.sh”并回车.

2.6  在当前目录执行命令“bash winpidgin-build-fetcher.sh”。当执行该命令时会自动在C:/cygwin/home/Administrator/pidgin-temp目录下载一些编译pidgin要用到的软件包 

下载完这些包后就自动安装这些软件包,最后自动下载pidgin-2.4.0源码包。

2.7  最后执行 make –f Makefile.mingw install 命令(第一次运行这个命令的时候 make 出现错误,接着从新输入这个命令 make 成功) 在目录: C:/cygwin/home/Administrator/pidgin-2.4.0/win32-install-dir下生成安装文件。

2.8 同时也可以参考http://blog.csdn.net/happyhell/archive/2008/11/19/3336086.aspx该文章详细介绍了Pidgin的编译方法。

 

 

 

 

1) change export in file “/etc/profile”
DEV_BASE=/win32-dev
PATH=$DEV_BASE/gcc-core-4.4.0-mingw32-dll/bin:$DEV_BASE/gettext-0.17/bin:$DEV_BASE/enchant_1.6.0_win32/bin:$DEV_BASE/gtk_2_0-2.14/bin:$DEV_BASE/gtkspell-2.0.16/bin:$DEV_BASE/js-1.8.5-mingw32/bin:$DEV_BASE/libcurl/bin:$DEV_BASE/libxml2-2.9.0/bin:$DEV_BASE/meanwhile-1.0.2_daa3/bin:$DEV_BASE/nss-3.13.6-nspr-4.9.2/bin:$DEV_BASE/silc-toolkit-1.1.10/bin:$DEV_BASE/sqlite3/bin:$DEV_BASE/zlib/bin:$PATH
export PATH

LD_LIBRARY_PATH=$DEV_BASE/gcc-core-4.4.0-mingw32-dll/lib:$DEV_BASE/gettext-0.17/lib:$DEV_BASE/enchant_1.6.0_win32/lib:$DEV_BASE/gtk_2_0-2.14/lib:$DEV_BASE/gtkspell-2.0.16/lib:$DEV_BASE/js-1.8.5-mingw32/lib:$DEV_BASE/libcurl/lib:$DEV_BASE/libxml2-2.9.0/lib:$DEV_BASE/meanwhile-1.0.2_daa3/lib:$DEV_BASE/nss-3.13.6-nspr-4.9.2/lib:$DEV_BASE/silc-toolkit-1.1.10/lib:$DEV_BASE/sqlite3/lib:$DEV_BASE/zlib/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH

PKG_CONFIG_PATH=$DEV_BASE/gcc-core-4.4.0-mingw32-dll/lib/pkgconfig:$DEV_BASE/gettext-0.17/lib/pkgconfig:$DEV_BASE/enchant_1.6.0_win32/lib/pkgconfig:$DEV_BASE/gtk_2_0-2.14/lib/pkgconfig:$DEV_BASE/gtkspell-2.0.16/lib/pkgconfig:$DEV_BASE/js-1.8.5-mingw32/lib/pkgconfig:$DEV_BASE/libcurl/lib/pkgconfig:$DEV_BASE/libxml2-2.9.0/lib/pkgconfig:$DEV_BASE/meanwhile-1.0.2_daa3/lib/pkgconfig:$DEV_BASE/nss-3.13.6-nspr-4.9.2/lib/pkgconfig:$DEV_BASE/silc-toolkit-1.1.10/lib/pkgconfig:$DEV_BASE/sqlite3/lib/pkgconfig:$DEV_BASE/zlib/lib/pkgconfig:$PKG_CONFIG_PATH
export PKG_CONFIG_PATH

 

2) change file “/etc/fstab”:

d:/pidgin/win32-dev /win32-dev
d:/pidgin/win32-dev/perl-5.10.0 /opt/perl

 

3)
cd /d/pidgin/pidgin-2.10.7

./configure —without-x –disable-gstreamer –disable-vv –disable-idn  –disable-avahi –disable-dbus –disable-nss –disable-gnutls –disable-tcl

NOTE: disable nss & gnutls : openssl MSN, Yahoo!, Novell Groupwise, Google Talk