加入收藏 | 设为首页 | 会员中心 | 我要投稿 源码门户网 (https://www.92codes.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

linux网络编程之socket(九) 使用select函数改进客户端/服务器端程序

发布时间:2016-09-21 05:31:57 所属栏目:Linux 来源:站长网
导读:一、当我们使用单进程单连接且使用readline修改后的客户端程序,去连接使用readline修改后的服务器端程序,会出 现一个有趣的现象,先来看输出: 先运行服务器

客户端程序阻塞在了fgets 那里,即从标准输入读取数据,所以不能执行到下面的readline,也即不能返回0,不会退出 循环,不会调用close关闭sock,所以出现上述的情况,即状态停滞,不能向前推进。具体的状态变化可以参见这里。

出现上述问题的根本原因在于客户端程序不能并发处理从标准输入读取数据和从套接字读取数据两个事件,我们可 以使用前面讲过的select函数来完善客户端程序,如下所示:

void do_echocli(int sock)
{
    fd_set rset;
    FD_ZERO(&rset);
    
    int nready;
    int maxfd;
    int fd_stdin = fileno(stdin); //
    if (fd_stdin > sock)
        maxfd = fd_stdin;
    else
        maxfd = sock;
    
    char sendbuf[1024] = {0};
    char recvbuf[1024] = {0};
    
    while (1)
    {
    
        FD_SET(fd_stdin, &rset);
        FD_SET(sock, &rset);
        nready = select(maxfd + 1, &rset, NULL, NULL, NULL); //select返回表示检测到可读事件
        if (nready == -1)
            ERR_EXIT("select error");
    
        if (nready == 0)
            continue;
    
        if (FD_ISSET(sock, &rset))
        {
    
            int ret = readline(sock, recvbuf, sizeof(recvbuf)); //按行读取
            if (ret == -1)
                ERR_EXIT("read error");
            else if (ret  == 0)   //服务器关闭
            {
                printf("server closen");
                break;
            }
    
            fputs(recvbuf, stdout);
            memset(recvbuf, 0, sizeof(recvbuf));
        }
    
        if (FD_ISSET(fd_stdin, &rset))
        {
    
            if (fgets(sendbuf, sizeof(sendbuf), stdin) == NULL)
                break;
    
            writen(sock, sendbuf, strlen(sendbuf));
            memset(sendbuf, 0, sizeof(sendbuf));
        }
    }
    
    close(sock);
}

即将两个事件都添加进可读事件集合,在while循环中,如果select返回说明有事件发生,依次判断是哪些事件发生,如 果是标准输入有数据可读,则读取后再次回到循环开头select阻塞等待事件发生,如果是套接口有数据可读,且返回为0则 说明对方已经关闭连接,退出循环并调用close关闭sock。

重复前面的实验过程,把客户端换成使用select函数修改 后的程序,可以看到最后的输出:

simba@ubuntu:~$ netstat -an | grep tcp | grep 5188

tcp        0      0 0.0.0.0:5188            0.0.0.0:*               LISTEN

tcp        0      0 127.0.0.1:5188          127.0.0.1:54007         TIME_WAIT

(编辑:源码门户网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读