什么是句柄?
句柄(handle),有两种解释
第一种解释:句柄是一种特殊的智能指针 。当一个应用程序要引用其他系统(如数据库、操作系统)所管理的内存块或对象时,就要使用句柄。
第二种解释:整个Windows编程的基础。
句柄是Windows用来标识被应用程序所建立或使用的对象的唯一整数,Windows使用各种各样的句柄标识诸如应用程序实例,窗口,控制,位图,GDI对象等等。
一个句柄是指使用的一个唯一的整数值,即一个4字节(64位程序中为8字节)长的数值,来标识应用程序中的不同对象和同类中的不同的实例,诸如,一个窗口,按钮,图标,滚动条,输出设备,控件或者文件等。应用程序能够通过句柄访问相应的对象的信息,但是句柄不是指针,程序不能利用句柄来直接阅读文件中的信息。如果句柄不在I/O文件中,它是毫无用处的。 句柄是Windows用来标志应用程序中建立的或是使用的唯一整数,Windows大量使用了句柄来标识对象。
什么是句柄泄露?
“泄漏”是我们写程序的人老生常谈的一个话题。最为常见的就是内存泄漏(memory leak),本文介绍一种新的泄漏—句柄泄漏(handle leak)。在windows系统的程序中,我们经常会遇到句柄这个词,而且windows也抽象出了一种句柄类型HANDLE。在unix系统的系统中,句柄这个词用的不是很多。我们用另一个词描述它—文件描述符(file descriptior)。这里的文件是指广义的文件,因为在unix系统中,everything is a file。总的说来,句柄是指操作系统给我们的应用程序的进程分配的,用来标识某种资源的符号。这里的资源,可以是狭义的文件,可以是socket连接,也可以是一个对象。
现在,这里以linux环境中的一个socket连接中的句柄泄漏的例子来说明句柄泄漏的情况:有三个应用程序A,B,C,它们运行在不同的机器上,它们之间通过socket接口进行通信。其中A和B之间通信,A是服务端;B是客户端,B和C之间通信,B是服务端,C是客户端。它们之间的通信都是TCP的。现在,B要给A发送数据,B在发送前,如果发现和A之间的连接断开,就会去重连,在重连的时候,B并没有close已经断开连接的socket id。这样,B重连A多次之后,操作系统分配给它的socket id都将会被用完。那么,现在C如果来连接B, 就会出现B拒绝C连接的情况,为什么会这样呢?因为B进程里面已经没有可用来标识该连接的socket id,所以B只能拒绝服务。
上面就是一个socket句柄泄漏的例子。解决上面的问题的具体方法是:在B每次重连A的时候,调用系统提供的close()函数,把已经断开连接的socket的socket id释放。 举上面的例子,一方面是说明句柄泄漏的一种情况,另一方面,也是比较重要的方面,是让大家重视句柄的使用,能够正确使用句柄,一定要做到申请一个,就要时刻记得释放一个,要把申请和释放一一对应起来。就像内存使用中的malloc/free, new/delete一样,句柄的使用,申请和释放的api也要配对使用;
其它:
套接字(socket)是一个抽象层,应用程序可以通过它发送或接收数据,可对其进行像对文件一样的打开、读写和关闭等操作。套接字允许应用程序将I/O插入到网络中,并与网络中的其他应用程序进行通信。网络套接字是IP地址与端口的组合。为了满足不同的通信程序对通信质量和性能的要求,一般的网络系统提供了三种不同类型的套接字,以供用户在设计网络应用程序时根据不同的要求来选择。这三种套接为流式套接字(SOCK-STREAM)、数据报套接字(SOCK-DGRAM)和原始套接字(SOCK-RAW)。