分类目录归档:Linux

原来Linux和Windows下的socket还是有那么多不同的

之前以为linux和windows下的socket都是符合posix标准的,在一个环境下能够正常使用在另外一个环境也没问题。但没想到两者还是有那么多不同。

1.最先发现的是在windows上需要调用那个WSAStartup进行初始化才能使用socket。

2.linux下关闭socket用close,而windows上用closesocket。

3.后来发现shutdown的参数名称不同,windows上用SD_BOTH,linux上是SHUT_RDWR。

4.在linux下如果不正常关闭socket会触发SIGPIPE异常,所以我使用signal( SIGPIPE, SIG_IGN );忽略之。

5.linux下可以使用read,write函数操作socket,也可以使用send,recv。windows上只能使用send,recv?(不考虑udp的sendfrom和recvfrom)

今天又发现一个很大的不同点了,造成了homeserver在短时间内生成了一个20GB的日志文件,用完了vps的硬盘空间。如果一个正在使用中的socket使用close来关闭之而不调用shutdown,则该socket还是处于连接中,只是在进程的文件描述符中移除了(right?)所以导致了使用那个socket的线程一直没有收到关闭信号,阻塞在socket的recv上无法被关闭。而在windows上调用closesocket就彻底地断开了连接了。

下面是网上提供的信息:
close—–关闭本进程的socket id,但链接还是开着的,用这个socket id的其它进程还能用这个链接,能读或写这个socket id
shutdown–则破坏了socket 链接,读的时候可能侦探到EOF结束符,写的时候可能会收到一个SIGPIPE信号,这个信号可能直到socket buffer被填充了才收到,shutdown还有一个关闭方式的参数,0 不能再读,1不能再写,2 读写都不能。

所以,以后关闭socket还是同时使用shutdown和close好。

 

补充一下(2010-06-13):
1、在linux下,shutdown会引起在recv和send中阻塞的线程返回-1。但是在windows下,除非closesocket,否则线程仍然阻塞。

2、windows的描述符是递增的,linux的描述符是重用的。也就是说你在linux下关闭了描述符0,然后打开一个文件,这个文件就是用了描述符0。

Windows上模仿Linux下的time程序:wintime

程序和源代码下载:upfiles/wintime.zip

Usage: wintime program
Time Recording Method:
real    The real time the program REALLY runs.
user    The time the program runs in USER mode.
sys     The time the program runs in KERNEL mode.

使用示例(亦可以把程序拖到wintime.exe运行):

E:>wintime amend < amend/amend9.in
80

real    0m0.734
user    0m0.750
sys     0m0.000

示例2:

E:>wintime a
1
2 2
3 3 3
4 4 4 4
5 5 5 5 5

real    0m0.015
user    0m0.015
sys     0m0.000

转载:《Unix、Gnu、Windows与明王朝、李自成、满清的相似性分析》

以下内容来自http://blog.csdn.net/duyanning/archive/2007/09/25/1800111.aspx,本人不发表任何观点,大家可以公证评论。

Unix:崇祯明王朝
GNU nux:李自成的农民起义军
Windows:满清
IBM:蒙古北元
计算机用户:山海关总兵吴三桂
易用性:陈圆圆

李自成农民起义军本来的敌人是明王朝(GNU is not Unix)。
满清原本不过是关外一个落后而弱小的野蛮民族(MS-DOS),仰望并粗陋地模仿着天朝(Unix)的一切。
北元,曾经不可一世的世界霸主,此时退居漠北偏安一隅。
满清在对北元既联合又打击的过程中逐渐壮大(从IBM-PC的DOS到微软自己的Windows)。
此时的明王朝已步入迟暮之年,在农民起义军的烽火中摇摇欲坠,关外是刚刚强大起来虎视眈眈的满清。

鹿死谁手,就要看吴三桂倒向哪一边了,这一切还得由陈圆圆最终决定。

Linux下动态加载链接库

必须包含头文件 dlfcn.h。

使用到dlopen, dlclose, dlsym 3个主要函数,dlerror可以获取加载中遇到的错误的字符串。

下面给出部分代码,来自最新版homeserver:

	DBG("Loading plugin [%s]", name );
#ifdef __WIN32__
	p->handle = LoadLibrary( path );
	if( p->handle ){
		p->entry = (plugin_entry) GetProcAddress( p->handle,"plugin_entry");//
		p->cleanup = (plugin_entry) GetProcAddress( p->handle,"plugin_cleanup");//
	}
	if( !p->handle || p->entry==NULL ){
		DBG("# Loading plugin: %s failed: %d", path, GetLastError() );
#else
//linux
	p->handle = (int)dlopen( path, RTLD_LAZY );
	if( p->handle ){
		p->entry = (plugin_entry) dlsym( (void*)p->handle,"plugin_entry");//
		p->cleanup = (plugin_entry) dlsym( (void*)p->handle,"plugin_cleanup");//
	}
	if( !p->handle || p->entry==NULL ){
		DBG("# Loading plugin: %s failed: %s", path, dlerror() );
#endif

homeserver的源代码下载链接:

homeserver090930

Linux下使用readdir查找文件

在Windows上一直使用_findfirst查找文件,以为是标准库里的,可以在Linux下直接使用。今晚试了一下失败了。
Linux下使用readdir来扫描一个目录下的项目。首先,需要包含头文件dirent.h。然后定义下面搜索需要的结构。

DIR* dir_info; //目录指针
struct dirent* dir_entry; //目录项信息指针

//打开一个待扫描的目录
dir_info = opendir(“./plugins”);
if( dir_info ){
        //打开目录成功
while ( (dir_entry = readdir(dir_info)) != NULL)
{
             //忽略这两个特殊项目
             if(strcmp(dir_entry->d_name, “..”)==0 || strcmp(dir_entry->d_name, “.”)==0)
continue;
             //具体操作。。。
plugin_create( srv, dir_entry->d_name );
} // while
        //使用完毕,关闭目录指针。
        closedir(dir_info);
}

可惜,我没有找到有能够在windows和linux通用的文件扫描函数。所以只好用宏定义不同平台的处理方案。

#ifdef __WIN32__

#else

#endif