网络编程(29)—— socket的close函数以及shutdown函数在多进程服务器中的不同表现(二)
2016-12-07 00:21
387 查看
本文紧接着上一遍文章《socket的close函数以及shutdown函数在多进程服务器中的不同表现(一)》,来验证上文中提到的几个结论:
int main()
{
int sock1,sock2;
sock1=socket(AF_INET,SOCK_STREAM,0);
sock2=sock1;
printf("sock1=%d\n",sock1);
printf("sock2=%d\n",sock2);
return 0;
}
验证原理很简单,代码不再赘述,结果如下:
[Hyman@Hyman-PC multiProcess]$ ./a.out
sock1=3
sock2=3
很显然,结果证明了我们的结论,复制后的socket描述符指向同一个socket。
在试验之前,我们要先准备一个回声服务器,之前我很多文章中都有过描述,这里不再赘述,我们在客户端中验证这个问题,请看下面的代码:
int main(int argc,char* argv[])
{
pid_t pid;
int sout,result;
int sock;
struct sockaddr_in addr;
char buf[1024];
sock=socket(AF_INET,SOCK_STREAM,0);
memset(&addr,0,sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=inet_addr(argv[1]);
addr.sin_port=htons(atoi(argv[2]));
connect(sock,(struct sockaddr*)&addr,sizeof(addr));
pid=fork();
if(pid==0)
{
close(sock);
}
else
{
sleep(2);
write(sock,"hello world\n",12);
read(sock,buf,1024);
fputs(buf,stdout);
}
return 0;
}
代码中用fork()创建了一个子进程,然后在子进程中关闭了socket,而主进程中,为了防止在子进程close(sock)之前执行write(sock,"hello
world\n",12);这段代码,sleep了2秒钟,接着发送”hello world”,如果结论正确,此时的”hello world”字符串是可以被回声服务器发送回来的,然后打印接收到的字符串。也就是说结论成立的话,程序会打印一行”hello
world”。
是不是和我们预期的结果一致呢?请看下面的结果:
[Hyman@Hyman-PC multiProcess]$ ./a.out 127.0.0.1 9990
hello world
不出所料,close()函数果然未生效,证明了我们的结论。
值得注意的是我们要验证的结论:在多进程中存在同一个socket的副本的话,才会无法close()掉!因为不管标准输出还是socket都是系统级别的存在,操作系统会负责统计每个进程中是否存在指向同一个socket的文件描述符,从而根据文件描述符的数量,控制对应socket的关闭。
shutdown(sock,SHUT_WR); 我们会发现,程序不再打印数据:
[Hyman@Hyman-PC multiProcess]$ ./a.out 127.0.0.1 9990
[Hyman@Hyman-PC multiProcess]$
OK,所有结论验证成功!
Github位置:
https://github.com/HymanLiuTS/NetDevelopment
克隆本项目:
git clone
git@github.com:HymanLiuTS/NetDevelopment.git
获取本文源代码:
git checkout NL29
1、 复制后的socket描述符真的指向同一个socket吗?
为了验证这个问题,我们先创建一个socket,然后复制一份改socket描述符的副本,再分别打印这两个socket描述符,若描述符打印结果一致,说明指向同一个socket。int main()
{
int sock1,sock2;
sock1=socket(AF_INET,SOCK_STREAM,0);
sock2=sock1;
printf("sock1=%d\n",sock1);
printf("sock2=%d\n",sock2);
return 0;
}
验证原理很简单,代码不再赘述,结果如下:
[Hyman@Hyman-PC multiProcess]$ ./a.out
sock1=3
sock2=3
很显然,结果证明了我们的结论,复制后的socket描述符指向同一个socket。
2、 关闭多进程中指向同一个socket的描述符中的一个,真的无法关闭这个socket吗
为了验证这个问题,我们进行下面的试验。在试验之前,我们要先准备一个回声服务器,之前我很多文章中都有过描述,这里不再赘述,我们在客户端中验证这个问题,请看下面的代码:
int main(int argc,char* argv[])
{
pid_t pid;
int sout,result;
int sock;
struct sockaddr_in addr;
char buf[1024];
sock=socket(AF_INET,SOCK_STREAM,0);
memset(&addr,0,sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=inet_addr(argv[1]);
addr.sin_port=htons(atoi(argv[2]));
connect(sock,(struct sockaddr*)&addr,sizeof(addr));
pid=fork();
if(pid==0)
{
close(sock);
}
else
{
sleep(2);
write(sock,"hello world\n",12);
read(sock,buf,1024);
fputs(buf,stdout);
}
return 0;
}
代码中用fork()创建了一个子进程,然后在子进程中关闭了socket,而主进程中,为了防止在子进程close(sock)之前执行write(sock,"hello
world\n",12);这段代码,sleep了2秒钟,接着发送”hello world”,如果结论正确,此时的”hello world”字符串是可以被回声服务器发送回来的,然后打印接收到的字符串。也就是说结论成立的话,程序会打印一行”hello
world”。
是不是和我们预期的结果一致呢?请看下面的结果:
[Hyman@Hyman-PC multiProcess]$ ./a.out 127.0.0.1 9990
hello world
不出所料,close()函数果然未生效,证明了我们的结论。
值得注意的是我们要验证的结论:在多进程中存在同一个socket的副本的话,才会无法close()掉!因为不管标准输出还是socket都是系统级别的存在,操作系统会负责统计每个进程中是否存在指向同一个socket的文件描述符,从而根据文件描述符的数量,控制对应socket的关闭。
3、 Shutdown函数这么神奇?可以同时关闭多个socket描述符?
验证这个问题,其实非常简单,只需要将上述客户端代码中子进程关闭socket的函数close换成shutdown即可:shutdown(sock,SHUT_WR); 我们会发现,程序不再打印数据:
[Hyman@Hyman-PC multiProcess]$ ./a.out 127.0.0.1 9990
[Hyman@Hyman-PC multiProcess]$
OK,所有结论验证成功!
Github位置:
https://github.com/HymanLiuTS/NetDevelopment
克隆本项目:
git clone
git@github.com:HymanLiuTS/NetDevelopment.git
获取本文源代码:
git checkout NL29
相关文章推荐
- 网络编程(28)—— socket的close函数以及shutdown函数在多进程服务器中的不同表现(一)
- 网络编程socket之close与shutdown函数
- socket编程:客户端与服务器间的连接以及各函数的用法
- linux网络编程之socket(十):shutdown 与 close 函数 的区别
- linux网络编程之socket(十):shutdown 与 close 函数 的区别
- linux网络编程之socket(十):shutdown 与 close 函数 的区别
- socket编程:客户端与服务器间的连接以及各函数的用法
- Linux网络编程:TCP服务器(单进程多用户),使用select方法实现
- 网络编程socket之accept函数
- Linux下socket编程的辅助函数:select()函数以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET
- linux网络编程常用函数详解与实例(socket-->bind-->listen-->accept)
- linux网络编程常用函数详解与实例(socket-->bind-->listen-->accept)
- 网络编程socket之bind函数
- Java 网络编程 服务器Socket
- IPv6下网络编程socket, TCP和UDP例子,以及兼容IPV4和IPV6的类
- 网络编程socket之connect函数
- socket编程的理解-------解决不同主机上进程之间的通信
- linux网络编程常用函数详解与实例(socket-->bind-->listen-->accept)
- linux网络编程常用函数详解与实例(socket-->bind-->listen-->accept)
- socket编程:从send函数和sendto函数参数的不同看TCP和UDP的差别。