免费注册 查看新帖 |

Chinaunix

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

IO多路转接(select)程序示例 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-01-13 16:31 |只看该作者 |倒序浏览

                                                /*
* name: tcp_slct.c
* written by saodrin zhang for test
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define SVC_PORT        9999
int main_serv(int argc, char *argv[]);
int main_clnt(int argc, char *argv[]);
int main(int argc, char *argv[])
{
    int ret;
    if (argc == 1)
        ret = main_serv(argc, argv);
    else
        ret = main_clnt(argc, argv);
    return ret;
}
#define MAX_CNCT_NUM 8
#define BUF_SIZE 256
int main_serv(int argc, char *argv[])
{
    int ret, i, k, n;
    int len;
    int inp_fd, sockfd, cnctfd, maxfd;
    int cepfd[MAX_CNCT_NUM], cepnum, entry; /* clntfd[], clntnum */
    int optval, sndFlag;
    fd_set readfds, writefds;
    struct sockaddr_in bindaddr;  //servaddr
    struct sockaddr_in cnctaddr;  //clntaddr
    struct timeval timeout;
    char text[BUF_SIZE], buf[BUF_SIZE];
    char sBuf[MAX_CNCT_NUM][BUF_SIZE];
    maxfd = 0;
    /*inp_fd = open("/dev/tty", O_RDONLY | O_NONBLOCK);*/
    inp_fd = fileno(stdin);
    printf("Inp_fd is %d\n", inp_fd); /* assert(inp_fd >= 0); */
    fcntl(inp_fd, F_SETFL, fcntl(inp_fd, F_GETFL) | O_NONBLOCK);
    /* assign the Protocol Family for communication */
    if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
    {
        printf("socket create error!\n");
        return -1;
    }
    memset(&bindaddr, 0, sizeof(struct sockaddr_in));
    /* AF_INET: Address Family */
    bindaddr.sin_family = AF_INET;
    /* INADDR_ANY: address of any interface owned by the host */
    bindaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    bindaddr.sin_port = htons(SVC_PORT);
    bzero(&(bindaddr.sin_zero), 8); /*  */
    /* 置 socket 重新使用  */
    optval = 1; /* option enable */
    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *) &optval, sizeof(optval)) = 0)
    {
        fcntl(inp_fd, F_SETFL, O_NONBLOCK);
    }
    if (sockfd >= 0)
    {
        fcntl(sockfd, F_SETFL, O_NONBLOCK);
    }
    text[0] = '\0';
    for (i = 0; i = 0)
        {
            FD_SET(sockfd, &readfds);
            maxfd = sockfd > maxfd ? sockfd : maxfd;
        }
        for (i = 0, n = 0; i  0)
            {
                FD_SET(cepfd, &readfds);
                if (sBuf[0] != '\0')
                {
                    /* printf("WR: FD_SET...\n"); */
                    FD_SET(cepfd, &writefds);
                }
                maxfd = cepfd > maxfd ? cepfd : maxfd;
                n++;
            }
        }
        ret = select(maxfd+1, &readfds, &writefds, NULL, &timeout);
        //select error when ret = -1
        if (ret == -1) printf("select error!\n");
        //time out when ret = 0
        //if (ret == 0) printf("select time out.\n");
        //data coming when ret>0
        if (ret > 0)
        {
            if (FD_ISSET(inp_fd, &readfds))
            {
                /*i = read(inp_fd, &ch, 1);
                if('\n' == ch) continue;
                else printf("Input is %c\n", ch);*/
                n = read(inp_fd, text, BUF_SIZE);
                if (n >= 0)
                {
                    i = 0;
                    k = 0;
                    while (i %d: Connection from %s:%d\n", ++cepnum, \
                           inet_ntoa(cnctaddr.sin_addr), cnctaddr.sin_port);
                    fcntl(cnctfd, F_SETFL, O_NONBLOCK);
                    cepfd[entry] = cnctfd; /* client fd */
                    for (i = 0; i  0 && FD_ISSET(cepfd, &readfds))
                {
                    n = read(cepfd, buf, BUF_SIZE);
                    if (n > 0)
                    {
                        buf[n] = '\0';
                        printf("RD cepfd[%d]: %s", i, buf);
                        k++;
                        if (buf[0] != '\0' && text[0] != '\0')
                        {
                            sprintf(sBuf, "%s + ", text);
                            strcat(sBuf, buf);
                        }
                    }
                    else if (n == 0)
                    {
                        printf("RD cepfd[%d]: peer is closed.\n", i);
                        shutdown(cepfd, SHUT_RDWR);
                        cepfd = -1;
                        close(cepfd);
                        cepnum--;
                    }
                    else
                    {
                        switch (errno)
                        {
                        case EAGAIN:
#if EWOULDBLOCK != EAGAIN
                        case EWOULDBLOCK:
#endif
                            k++;
                            break;
                        case EINTR:
                            /* we were stopped _before_ we had a connection */
                        case ECONNABORTED: /* this is a FreeBSD thingy */
                            /* we were stopped _after_ we had a connection */
                            k++;
                            break;
                        case EMFILE: /* out of fds */
                            k++;
                            break;
                        default:
                            perror("read");
                            cepfd = -1;  /* close it */
                            cepnum--;
                            break;
                        } /* end switch (errno) */
                    } /* end if (n > 0) */
                } /* end if (cepfd > 0 && FD_ISSET(cepfd, &readfds)) */
            } /* end for (...; i  0 && FD_ISSET(cepfd, &writefds))
                {
                    len = strlen(sBuf);
                    n = write(cepfd, sBuf, len);
                    if (n > 0) /* assert(n == len); */
                    {
                        printf("WR cepfd[%d]: %s", i, sBuf);
                        k++;
                        sBuf[0] = '\0';
                    }
                    else if (n == 0)
                    {
                        printf("WR cepfd[%d]: peer is closed.", i);
                        cepfd = -1;
                        cepnum--;
                        sBuf[0] = '\0';
                    }
                    else /* error */
                    {
                        switch (errno)
                        {
                        case EAGAIN:
#if EWOULDBLOCK != EAGAIN
                        case EWOULDBLOCK:
#endif
                            k++;
                            break;
                        case EINTR:
                            /* we were stopped _before_ we had a connection */
                        case ECONNABORTED: /* this is a FreeBSD thingy */
                            /* we were stopped _after_ we had a connection */
                            k++;
                            break;
                        case EMFILE: /* out of fds */
                            k++;
                            break;
                        default:
                            perror("read");
                            cepfd = -1;  /* close it */
                            cepnum--;
                            break;
                        } /* end switch (errno) */
                    } /* end if (n > 0) */
                } /* end if (cepfd > 0 && FD_ISSET(cepfd, &readfds)) */
            } /* end for (...; i  0) */
    }
    return 0;
}
int main_clnt(int argc, char *argv[])
{
    int ret, i, n;
    int len;
    int inp_fd, sockfd, cnctfd, maxfd;
    int cepfd[MAX_CNCT_NUM], cepnum, entry;
    int optval, sndFlag;
    fd_set readfds, writefds;
    struct sockaddr_in bindaddr;   //local client address
    struct sockaddr_in cnctaddr;   //remote server address
    struct timeval timeout;
    struct hostent    *host;
    struct in_addr servAddr;
    unsigned long servIP;
    char text[BUF_SIZE], buf[BUF_SIZE];
    if (argc h_addr_list[0], sizeof(struct in_addr));
        servIP = ntohl(servAddr.s_addr);
        printf("destIP = 0x%x\n", servIP);
    }
    else
    {
        printf("Error: gethostbyname\n");
        return -1;
    }
    /*inp_fd = open("/dev/tty", O_RDONLY | O_NONBLOCK);*/
    inp_fd = fileno(stdin);
    printf("Inp_fd is %d\n", inp_fd); /* assert(inp_fd >= 0); */
    fcntl(inp_fd, F_SETFL, fcntl(inp_fd, F_GETFL) | O_NONBLOCK);
    maxfd = inp_fd;
    /* assign the Protocol Family for communication */
    if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
    {
        printf("socket create error!\n");
        return -1;
    }
    memset(&bindaddr, 0, sizeof(struct sockaddr_in));
    /* AF_INET: Address Family */
    bindaddr.sin_family = AF_INET;
    /* INADDR_ANY: address of any interface owned by the host */
    bindaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    bindaddr.sin_port = htons(SVC_PORT);
    bzero(&(bindaddr.sin_zero), 8); /*  */
    /* 置 socket 重新使用  */
    optval = 1; /* option enable */
    //if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *) &optval, sizeof(optval))  maxfd ? cnctfd : maxfd;
    while (1)
    {
        timeout.tv_sec = 1;
        timeout.tv_usec = 0;
        FD_ZERO(&readfds);
        FD_ZERO(&writefds);
        FD_SET(inp_fd, &readfds);
        FD_SET(cnctfd, &readfds);
        if (sndFlag != 0) FD_SET(cnctfd, &writefds);
        ret = select(maxfd+1, &readfds, &writefds, NULL, &timeout);
        //select error when ret = -1
        if (ret == -1) printf("select error\n");
        //time out when ret = 0
        //if (ret == 0) printf("select time out\n");
        //data coming when ret>0
        if (ret > 0)
        {
            if (FD_ISSET(inp_fd, &readfds))
            {
                /*i = read(inp_fd, &ch, 1);
                if('\n' == ch) continue;
                else printf("Input is %c\n", ch);*/
                n = read(inp_fd, text, BUF_SIZE);
                if (n >= 0)
                {
                    text[n] = '\0';
                }
                else
                {
                    printf("RD STDIN error!\n");
                    text[0] = '\0';
                }
                if ('\n' == text[0]) continue;
                else printf("Inputed: %s", text);
                if ('q' == text[0]) break;
                else sndFlag = 1;
            }
            if (FD_ISSET(cnctfd, &readfds))
            {
                n = recv(cnctfd, buf, BUF_SIZE, MSG_DONTROUTE);
                if (n > 0)
                {
                    buf[n] = '\0';
                    printf("Recv OK: %s", buf);
                }
                else if (n == 0) /* peer is closed */
                {
                    printf("Peer is closed ...\n");
                    shutdown(cnctfd, SHUT_RDWR);
                    close(cnctfd);
                    break;
                }
                else
                {
                    printf("Recv error!\n");
                }
            }
            if (FD_ISSET(cnctfd, &writefds))
            {
                if ((n = strlen(text)) > 0)
                {
                    if ((i = send(cnctfd, text, n, MSG_DONTROUTE)) != n)
                    {
                        printf("Try to send again...\n");
                        sndFlag = 1;
                    }
                    else
                    {
                        printf("Send OK: %s", text);
                        sndFlag = 0;
                    }
                }
                else
                {
                    sndFlag = 0; /* FD_CLR(cnctfd, &writefds); */
                    printf("Nothing to be sent\n");
                    if ((i = write(cnctfd, "...\n", 4)) != 4)
                        perror("Test write");
                } /* end if ((n = strlen(text)) > 0) */
            } /* end if (FD_ISSET(cnctfd, &writefds)) */
        } /* end if (ret > 0) */
    } /* end while (1) */
    return ret;
}
               
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/3771/showart_2147699.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP