select 在socket通信中的应用

来源:互联网 发布:php大马 编辑:程序博客网 时间:2024/05/16 19:24

//----------------------------------------------------

//AUTHOR: lanyang123456

//DATE: 2014-10-12

//----------------------------------------------------



代码实例如下:



/*TCPserver_v2.0use selectAPIinet_aton()inet_ntoa()*/#include<stdio.h>#include<stdlib.h>#include<string.h>#include<errno.h>#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#define LENGTH_OF_LISTEN_QUEUE20#define SERVER_PORT6666#define MAXLINE 4096#define MAX_FD_NUM2int main(int argc, char** argv){int    listenfd, connfd;struct sockaddr_inservaddr;struct sockaddr_inclient_addr;socklen_t client_addr_len = sizeof(client_addr);char    recv_buff[4096]; char    response[] = "recv well done.";int     recv_len;fd_set readfd;intret;intfdset[MAX_FD_NUM] = {-1, -1};intmax_fd;inti;if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ) {    printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);    exit(0);}fdset[0] = listenfd;max_fd = listenfd;memset(&servaddr, 0, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);servaddr.sin_port = htons(SERVER_PORT);if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) {    printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);    exit(0);}if (listen(listenfd, LENGTH_OF_LISTEN_QUEUE) == -1) {    printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);    exit(0);    }printf("----------waiting for client's request---------\n");while (1) {        /*每次调用select前,都要重置监听的描述符*/  FD_ZERO(&readfd);for (i=0; i < MAX_FD_NUM; i++) {if (fdset[i] != -1) {FD_SET(fdset[i], &readfd);}}ret = select(max_fd + 1, &readfd, NULL, NULL, NULL);//有数据时才返回        if (ret == -1) {  //错误情况if (errno == EINTR) {//signal interruptcontinue;}else {perror("select error");exit(0);}}        else if (ret) {    //返回值大于0 有数据到来            if (FD_ISSET(listenfd, &readfd))            {if((connfd = accept(listenfd, (struct sockaddr *)&client_addr, &client_addr_len)) == -1) {        printf("accept socket error: %s(errno: %d)\n",strerror(errno),errno);        continue;    }printf("accept a new  connection from client: %s\n", inet_ntoa(client_addr.sin_addr));fdset[1] = connfd;max_fd = connfd;            } else if (FD_ISSET(connfd, &readfd)) {memset(recv_buff, 0, MAXLINE);    recv_len = recv(connfd, recv_buff, MAXLINE - 1, 0);if (recv_len <= 0) {printf("recv socket error: %s(errno: %d)\n",strerror(errno),errno);close(connfd);continue;}    recv_buff[recv_len] = '\0';    printf("recv msg %d byte from client: %s\n", recv_len, recv_buff);    if (send(connfd, response, strlen(response), 0) < 0) {    printf("send socket error: %s(errno: %d)\n", strerror(errno), errno);    close(connfd);continue;    }    //close(connfd);//fdset[1] = -1;//max_fd = listenfd;}}        else    //ret 为0,超时情况        {            printf("time out\n");//close(keybd_fd);//产生异常,查看结果        }}close(listenfd);exit(0);}


client 端可参考

http://blog.csdn.net/lanyang123456/article/details/40024327


注意的地方:

当client connect 成功建立,然后关闭sockfd。此时server端已成功接到客户端的连接,处于select阻塞状态,当客户端关闭连接时,select监控的描述符会有数据到来,select返回, 接着会调用recv, 并且recv立刻返回,返回值为0.也就是说客户端断开连接,select有事件发生,recv会立刻返回。





参考

http://blog.csdn.net/dlutbrucezhang/article/details/8577810

http://blog.csdn.net/microtong/article/details/4989902

http://blog.csdn.net/klarclm/article/details/8825930

http://www.oschina.net/code/snippet_97047_675


0 0
原创粉丝点击