今天看linux C 编程实战的my_server例子时,敲到这段代码,对其父子进程关闭socket 进行close调用产生疑问

如图中标注的三个close socket,思考子进程通信结束 关闭自己的通信socket:conn_fd可以理解,但将sock_fd,服务器的监听socket也关闭就不知怎么回事了。而且父进程执行close(conn_fd)将子进程的通信socket关闭,这样不久让子进程无法和客户端soket通信了吗? 但是程序正常运行。重新查资料发现是自己对子进程资源的复制和close函数,还有文件描述符的理解不到位

1. 首先,socket是一种特殊的数据传输IO,也是一种文件描述符。

2. fork创建进程时,子进程共享父进程打开的文件描述符,但父进程对文件描述符的改变不会影响子进程中的文件描述符。

3. close 一个套接字的默认行为是把套接字标记为已关闭,然后立即返回到调用进程,该套接字描述符不能再由调用进程使用,也就是说它不能再作为read或write的第一个参数,然而TCP将尝试发送已排队等待发送到对端的任何数据,发送完毕后发生的是正常的TCP连接终止序列。

  在多进程并发服务器中,父子进程共享着套接字,套接字描述符引用计数记录着共享着的进程个数,当父进程或某一子进程close掉套接字时,描述符引用计数会相应的减一,当引用计数仍大于零时,这个close调用就不会引发TCP的四路握手断连过程。

所以:父进程close(conn_fd)不会对子进程通信造成影响。相反,如果不这么做,在父进程中conn_fd占用着可用的文件描述符,会影响父进程accept链接的个数,因为conn_fd是有用户级限制的(内核为了不让某一个进程消耗掉所有的文件资源,其也会对单个进程最大打开文件数做默认值处理,默认值一般是1024,使用ulimit -n命令可以查看),再accept一个新的连接时,前一个conn_fd被覆盖,就找不到了,但相应的描述符值还是被标记为“占用”,当达到用户级限制时,不可再accept新连接,成为瓶颈。

在Web服务器中,通过更改系统默认值文件描述符的最大值来优化服务器是最常见的方式之一。具体优化方式请查看http://blog.csdn.net/kumu_linux/article/details/7877770 其中介绍的很详细

经本人亲测,如果去除了父进程的close(conn_fd),可以accept的连接数大大减少。而且通过修改系统文件描述符最大值,可以大大提高accept连接数量。

初学Linux 对其中很多细节还不清楚,后续会针对修改!

文件描述符讲解很好的博客:http://blog.csdn.net/cywosp/article/details/38965239

while() {
conn_fd = accept(sock_fd, (struct sockaddr *)&cli_addr, &cli_len);
if (conn_fd < ) {
my_err("accept", __LINE__);
}
printf("accept a new client, ip:%s\n", inet_ntoa(cli_addr.sin_addr));
if ((pid = fork()) == ) {
while() {
if ((ret = recv(conn_fd, recv_buf, sizeof(recv_buf), )) < ) {
perror("recv");
exit();
}
recv_buf[ret-] = '\0';
if (flag_recv == USERNAME) {
name_num = find_name(recv_buf);
switch(name_num) {
case -:
send_data(conn_fd, "n\n");
break;
case -:
exit();
break;
default:
send_data(conn_fd, "y\n");
flag_recv = PASSWORD;
break;
}
}
else if (flag_recv == PASSWORD) {
if (strcmp(users[name_num].password, recv_buf) == ) {
send_data(conn_fd, "y\n");
send_data(conn_fd, "welcome login my tcp server\n");
printf("%s login\n", users[name_num].username);
flag_recv = MESSAGE;
}
else {
send_data(conn_fd, "n\n");
}
}
else if (flag_recv == MESSAGE) {
if (strcmp("quit", recv_buf) == ) {
break;
}
printf("message from %s: %s\n", users[name_num].username, recv_buf);
}
}
close(sock_fd);
close(conn_fd);
printf("child exit!\n");
exit();
}else {
close(conn_fd); }

linuxC编程实战 my_server.c例子问题总结的更多相关文章

  1. 【Java并发编程实战】-----“J.U.C”:Exchanger

    前面介绍了三个同步辅助类:CyclicBarrier.Barrier.Phaser,这篇博客介绍最后一个:Exchanger.JDK API是这样介绍的:可以在对中对元素进行配对和交换的线程的同步点. ...

  2. 【Java并发编程实战】-----synchronized

    在我们的实际应用当中可能经常会遇到这样一个场景:多个线程读或者.写相同的数据,访问相同的文件等等.对于这种情况如果我们不加以控制,是非常容易导致错误的.在java中,为了解决这个问题,引入临界区概念. ...

  3. 在 Boolan 网开讲《网络编程实战》课程

    <网络编程实战>是一门以讲解实例为主的课程,每一节都讲一两个网络编程的例子程序,课程偏重 Linux 服务端 TCP 网络编程. 本课程要求听课人员已经读过<Unix 网络编程> ...

  4. Linux下的C编程实战

    Linux下的C编程实战(一) ――开发平台搭建 1.引言 Linux操作系统在服务器领域的应用和普及已经有较长的历史,这源于它的开源特点以及其超越Windows的安全性和稳定性.而近年来, Linu ...

  5. Shell高级编程视频教程-跟着老男孩一步步学习Shell高级编程实战视频教程

    Shell高级编程视频教程-跟着老男孩一步步学习Shell高级编程实战视频教程 教程简介: 本教程共71节,主要介绍了shell的相关知识教程,如shell编程需要的基础知识储备.shell脚本概念介 ...

  6. Scala 深入浅出实战经典 第66讲:Scala并发编程实战初体验

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...

  7. 跟着老男孩一步步学习Shell高级编程实战

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://oldboy.blog.51cto.com/2561410/1264627 本sh ...

  8. Linux下的编程实战【转】

    一篇比较不错的文章, 降到了 makefile make , gcc编译器,GDB调试器, Linux文件系统,Linux文件API,.C语言库函数(C库函数的文件操作实际上是独立于具体的操作系统平台 ...

  9. 《Go并发编程实战》读书笔记-语法概览

    <Go并发编程实战>读书笔记-语法概览 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 本篇博客我们会快速浏览一下Go的语法,内容涉及基本构成要素(比如标识符,关键字,子 ...

随机推荐

  1. lazyman学习

    1.安装: gem install lazyman 2.建立工程: cd到工程目录下 lazyman new 工程名 3.打开调试命令 lazyman c lazyman调用selenium-webd ...

  2. Hibernate(五)一对一单向关联映射

    上次的博文中 Hibernate从入门到精通(四)基本映射我们已经讲解了一下基本映射和相关概念,接下来 我们会讲稍微复杂点的映射——关系映射. 关系映射分类 关系映射即在基本映射的基础上处理 多个相关 ...

  3. Linux process state codes

    Here are the different values that the s, stat and state output specifiers (header "STAT" ...

  4. 实现自己的脚本语言ngscript之一:词法分析

    正则表达式的理论基础可以参考装配脑袋的 这个 自己动手开发编译器(二)正则语言和正则表达式 这个 自己动手开发编译器(三)有穷自动机 还有这个 自己动手开发编译器(四)利用DFA转换表建立扫描器 如果 ...

  5. ng-select ng-options ng-repeat的用法与区别

    最近在用angularJS里的ng-select,ng-options,ng-repeat,发现有两点不太方便: 1.当数据复杂时,循环起来比较麻烦 2.首选项如果不设置,就会为空 整理一下它们的用法 ...

  6. Jquery案例——某网站品牌列表的效果

    一下是效果图.点击"显示全部品牌",高亮推荐品牌,并显示全部品牌. HTML文件: <!DOCTYPE html> <html lang="en&quo ...

  7. mysql常用总结

    用户管理mysql>use mysql;查看mysql> select host,user,password from user ;创建mysql> create user zx_r ...

  8. eCos系统CPU负载测量

    原文:http://ecos.sourceware.org/docs-latest/ref/services-cpuload.html 译文:http://blog.csdn.net/zoomdy/a ...

  9. golang 学习笔记

    golan 声明的变量必须要用到? 语法 a,b:=2323; b为 bool 类型 结构体的赋值 需要用到逗号分隔字段 并且最后一个字段后也必须加上逗号 这和 JavaScript 的对象不一样哦 ...

  10. 小结 iOS 中的 copy

    预备知识 : 内存的栈区 : 由编译器自动分配释放, 存放函数的参数值, 局部变量的值等. 其 操作方式类似于数据结构中的栈. 内存的堆区 : 一般由程序员分配释放, 若程序员不释放, 程序结束时可能 ...