linuxC编程实战 my_server.c例子问题总结
今天看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例子问题总结的更多相关文章
- 【Java并发编程实战】-----“J.U.C”:Exchanger
前面介绍了三个同步辅助类:CyclicBarrier.Barrier.Phaser,这篇博客介绍最后一个:Exchanger.JDK API是这样介绍的:可以在对中对元素进行配对和交换的线程的同步点. ...
- 【Java并发编程实战】-----synchronized
在我们的实际应用当中可能经常会遇到这样一个场景:多个线程读或者.写相同的数据,访问相同的文件等等.对于这种情况如果我们不加以控制,是非常容易导致错误的.在java中,为了解决这个问题,引入临界区概念. ...
- 在 Boolan 网开讲《网络编程实战》课程
<网络编程实战>是一门以讲解实例为主的课程,每一节都讲一两个网络编程的例子程序,课程偏重 Linux 服务端 TCP 网络编程. 本课程要求听课人员已经读过<Unix 网络编程> ...
- Linux下的C编程实战
Linux下的C编程实战(一) ――开发平台搭建 1.引言 Linux操作系统在服务器领域的应用和普及已经有较长的历史,这源于它的开源特点以及其超越Windows的安全性和稳定性.而近年来, Linu ...
- Shell高级编程视频教程-跟着老男孩一步步学习Shell高级编程实战视频教程
Shell高级编程视频教程-跟着老男孩一步步学习Shell高级编程实战视频教程 教程简介: 本教程共71节,主要介绍了shell的相关知识教程,如shell编程需要的基础知识储备.shell脚本概念介 ...
- Scala 深入浅出实战经典 第66讲:Scala并发编程实战初体验
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...
- 跟着老男孩一步步学习Shell高级编程实战
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://oldboy.blog.51cto.com/2561410/1264627 本sh ...
- Linux下的编程实战【转】
一篇比较不错的文章, 降到了 makefile make , gcc编译器,GDB调试器, Linux文件系统,Linux文件API,.C语言库函数(C库函数的文件操作实际上是独立于具体的操作系统平台 ...
- 《Go并发编程实战》读书笔记-语法概览
<Go并发编程实战>读书笔记-语法概览 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 本篇博客我们会快速浏览一下Go的语法,内容涉及基本构成要素(比如标识符,关键字,子 ...
随机推荐
- 实现DataGridView实时更新数据
;).ToString() + ).ToString() + "秒"; } }}
- Unity3d fur真实毛发渲染
放出效果图 使用的核心技术为曲面细分和置换贴图,Unity支持GPU的曲面细分,置换贴图为噪波,沿着法线拉伸即成为毛发.再随机减少最高点的高度产生毛刺的感觉 曲面细分之前有篇文章详细讲过 弄了前后ri ...
- xgboost在windows上的安装
xgboost是一个boosting+decision trees的工具包,看微博上各种大牛都说效果很好,于是下载一个,使用了一下,安装步骤如下. 第一步,编译生成xgboost.exe(用于CLI) ...
- [Java] HashMap 导致的高 CPU 使用率
今天在生产环境遇到一个问题,Java 应用程序的 cpu 使用比例很高,导致整台机器的 cpu 使用率高达 90% ,正常情况下是 20% 左右. 把 Thread dump 导出来,利用 IBM T ...
- c#委托和事件(上)
C# 中的委托和事件 引言 委托 和 事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易.它们就像是一道槛儿,过了这个槛的人,觉得真 ...
- ELK初学搭建(elasticsearch)
ELK初学搭建(elasticsearch) elasticsearch logstash kibana ELK初学搭建 elasticsearch 1.环境准备 centos6.8_64 mini ...
- C#截取指定字符串函数
本文转载:http://www.cnblogs.com/liufei88866/archive/2012/05/12/2497395.html 一.通过函数方式进行获取. public string ...
- Android教程:ImageView 设置图片
Android doc中是这样描述的: public void setImageResource (int resId) 这是其中的一个方法,参数resld是这样: ImageView.setImag ...
- javascript中的稀疏数组(sparse array)和密集数组
学习underscore.js数组相关API的时候.遇到了sparse array这个东西,曾经没有接触过. 这里学习下什么是稀疏数组和密集数组. 什么是密集数组呢?在java和C语言中,数组是一片连 ...
- 支付宝手机网站支付流程(Node实现)
前言 公司M站要接入支付宝,借机研究了一下支付宝的支付流程.毕竟,只有公司才能拿到支付接口权限. 主要参考文档: https://doc.open.alipay.com/doc2/detail?tre ...