免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 5033 | 回复: 10
打印 上一主题 下一主题

[网络] linux套接字编程 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-08-01 12:11 |只看该作者 |倒序浏览
在调试unix网路编程的例子,内容如下:
#include        "unp.h"

int
main(int argc, char **argv)
{
        int                                        listenfd, connfd;
        pid_t                                childpid;
        socklen_t                        clilen;
        struct sockaddr_in        cliaddr, servaddr;

        listenfd = Socket(AF_INET, SOCK_STREAM, 0);

        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family      = AF_INET;
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        servaddr.sin_port        = htons(SERV_PORT);

        Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));

        Listen(listenfd, LISTENQ);

        for ( ; ; ) {
                clilen = sizeof(cliaddr);
                connfd = Accept(listenfd, (SA *) &cliaddr, &clilen);

                if ( (childpid = Fork()) == 0) {        /* child process */
                 
                        Close(listenfd);        /* close listening socket */     很奇怪的是,若没有注释这句,server的listen 进程就会没了????然后我把这句注释了,listen进程就会一直在
                        str_echo(connfd);        /* process the request */
                        exit(0);
                }
                Close(connfd);                        /* parent closes connected socket */
        }
}

#include        "unp.h"

void
str_echo(int sockfd)
{
        ssize_t                n;
        char                buf[MAXLINE];

again:
        while ( (n = read(sockfd, buf, MAXLINE)) > 0) //最后阻塞于这儿,再也没出来了,通过gdb看sockfd的确是有值。
//然后再看netstat -a | ps SERV_PORT
//发现有两个established 进程,与unix网络编程所说一致
//跟踪客户端,发现write是成功并返回的
//另外像这种阻塞套接字如何跟踪出问题的原因?
                Writen(sockfd, buf, n);


        if (n < 0 && errno == EINTR)
                goto again;
        else if (n < 0)
                err_sys("str_echo: read error");
}

论坛徽章:
0
2 [报告]
发表于 2012-08-02 00:20 |只看该作者
Close(listenfd);        /* close listening socket */     很奇怪的是,若没有注释这句,server的listen 进程就会没了????然后我把这句注释了,listen进程就会一直在

--这个原因是因为 父进程与子进程共享listenfd 描述符。调用close关闭描述符的时候,需要把描述符的引用数减1(此时为2),为1 。因为此时描述符引用为1 所以不真正关闭描述符~但是当 子进程exit(0); 后 则直接关闭listenfd描述符! 也即server的listen 进程就会没了! 注意close 与 exit 的区别!

论坛徽章:
0
3 [报告]
发表于 2012-08-02 10:01 |只看该作者
回复 2# xiyoulaoyuanjia

汗,那还真没注意到这点,这个代码是unix网络编程的源代码,也就是说这个算是一个错误?
   

论坛徽章:
0
4 [报告]
发表于 2012-08-02 10:03 |只看该作者
回复 2# xiyoulaoyuanjia
但又仔细看,实际code,会在函数str_echo阻塞住了,或者循环了,也就说说exit不会执行到,所以原因还是不在这儿?


   

论坛徽章:
0
5 [报告]
发表于 2012-08-02 10:21 |只看该作者
个人觉得 close 肯定不能注释掉! 因为父进程一直没有关 掉 监听套接字 所以 子进程在exit 之前一定要 close掉 监听套接字的!
回复 4# totopper


   

论坛徽章:
0
6 [报告]
发表于 2012-08-02 11:07 |只看该作者
回复 5# xiyoulaoyuanjia


    嗯,得再仔细看看其余部分的code,是谁导致listening的 进程关闭了

论坛徽章:
0
7 [报告]
发表于 2012-08-02 11:46 |只看该作者
fork()函数的作用是创建一个进程,子进程会将父进程的代码原样拷贝一份至子进程的进程空间中,在子进程中从fork()之后的位置继续执行代码,监听套接字是在创建子进程之前创建绑定的,所以父进程和子进程对listenfd的操作是一致的,因为listenfd的值一样,子进程close了,监听自然就关掉了,所以这个server只能接收一个client的连接请求,然后死循环read客户端发送的信息写入buf,如果想多client访问把close注掉就可以了,每出现一个client访问就创建一个进程进行通讯,引用数这个概念是面向对象提出来的吧?close就是把文件描述符指向的设备关掉了。

论坛徽章:
0
8 [报告]
发表于 2012-08-02 12:29 |只看该作者
参考 unp第二版 114页
回复 7# eossplendid


   

论坛徽章:
0
9 [报告]
发表于 2012-08-02 16:26 |只看该作者
不知道那是什么......
回复 8# xiyoulaoyuanjia


   

论坛徽章:
0
10 [报告]
发表于 2012-08-03 11:13 |只看该作者
1. 很奇怪的是,若没有注释这句,server的listen 进程就会没了????然后我把这句注释了,listen进程就会一直在

我这注释不注释都是正常监听的。

2.但是当 子进程exit(0); 后 则直接关闭listenfd描述符! 也即server的listen 进程就会没了! 注意close 与 exit 的区别!

子进程exit也是close(listenfd)吧 所引用的listenfd计数器减1吧。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP