今天看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. iOS不越狱装收费App——注册iOS设备为开发者工具

    额,这篇教程主要是我写下来用于总结注册iOS设备和用iResign安装App的过程,想要不越狱安装App当然有办法,但是有几个前提--你是一个Apple开发者,或者你有个朋友是App的开发者.如果没有 ...

  2. JavaScript高级程序设计13.pdf

    使用hasOwnProperty()方法检测一个属性存在实例还是原形中,当属性存在对象实例中时,返回true alert(person1.hasOwnProperty("name" ...

  3. hdoj 2141 Can you find it?【二分查找+暴力】

    Can you find it? Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 32768/10000 K (Java/Others ...

  4. IOS性能调优系列:Analyze静态分析

    目前关于IOS性能优化的教程较少,决定写一个<IOS性能调优系列>,主要关注与内存泄漏.性能优化.流量和电量分析几个方面. XCode已经提供了非常强大的性能调优工具,结合几个第三方工具和 ...

  5. 【Android - MD】之TabLayout的使用

    TabLayout是Android 5.0新特性--Material Design中的一个控件,是一个标签页的导航条,常结合ViewPager完成页面导航. 和其他MD控件一样,使用TabLayout ...

  6. Java 多线程并发 Future+callable 实例

    需求:一个业务实现 查询, 因为 要查询十几次, 所以每个平均0.6秒, 之前只有主线程一步步查 ,结果用了10秒,效率十分低下 , 于是改用线程池并发: 以下是代码设计: 1.线程池工具类: pac ...

  7. visual studio 添加链接文件

    本文转载http://blog.163.com/zhongpenghua@yeah/blog/static/87727415201282432345613/   那个有个箭头的文件就是链接文件了,添加 ...

  8. 未能从程序集“WindowsBase, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35“ 中加载“System.Windows.SplashSceen”

    通过添加windowsbase.dll,可以解决这个问题,你可以在自己的电脑上找到这个文件,地址是:C:\Program Files\Reference Assemblies\Microsoft\Fr ...

  9. The Arduino IDE(compiler)'s float bug

    1.通常直接使用串口的print函数就ok Serial.println(DHT.humidity);  //assuming DHT.humidity is float 2.但是习惯问题,还是偏好s ...

  10. android 26 设置项目有多个入口Activity。

    第一个activity package com.sxt.day04_11; import android.os.Bundle; import android.app.Activity; import ...