select()函数用法小结及疑问点

来源:互联网 发布:淘宝丝袜买家真人秀图 编辑:程序博客网 时间:2024/06/06 00:25

1、函数原型及头文件

- windows下头文件为
#include<WinSock2.h>


- linux下头文件为

#include<unistd.h>  
#include<sys/time.h>


- 原型

int select(int nfds,fd_set *readsets,fd_set *writesets,fd_set *exceptsets,const struct timeval *timeout)

返回值:就绪描述符的数目,超时返回0,出错返回-1


2、实测代码

着重要注意的点是:每次select结束后描述符的值会发生变化,所以每次循环开始要将read_fds和write_fds全部清理,然后将socketid重新fdset。
服务器端代码如下

#include <stdio.h>#include <string>#include <vector>#ifdef WINDOWS#include<WinSock2.h>#pragma comment(lib,"ws2_32.lib")#endif#ifdef LINUX#include<unistd.h>#include<stdio.h>#include<stdlib.h>#include<errno.h>#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#endif#pragma warning(disable:4996)#define DEFAULT_PORT 48000#define MAXLEN 4096void prepareIDs(int listen_fd,std::vector<int> accept_fd,int &max_fd,fd_set &read_fds,fd_set &write_fds){FD_ZERO(&read_fds);FD_ZERO(&write_fds);FD_SET(listen_fd, &read_fds);max_fd = listen_fd;for (auto itor = accept_fd.begin(); itor != accept_fd.end(); itor++){FD_SET(*itor, &read_fds);FD_SET(*itor, &write_fds);max_fd = max(max_fd, *itor);}max_fd += 1;}void doReadActions(int fd){char buff[4096];memset(buff, 0, sizeof(buff));int len = recv(fd, buff, MAXLEN, 0);printf("Receive buffer[%s]\n", buff);}void doWriteActions(int fd){char *buff = "This is the message sending from HOST.";send(fd, buff, strlen(buff)+1, 0);//printf("Host send message ok\n");}int main(){int listen_fd;struct sockaddr_in servaddr;fd_set readfds, writefds;std::vector<int> accept_fds;int max_fd;timeval timeout;timeout.tv_sec = 3;timeout.tv_usec = 500000;FD_ZERO(&readfds);FD_ZERO(&writefds);WSADATA initData;if (WSAStartup(MAKEWORD(2, 2), &initData)) {printf("Can not init socket");return -1;}if ((listen_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1){printf("create socket error: %s(errno: %d)\n", strerror(errno), errno);exit(0);}memset(&servaddr, 0, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);servaddr.sin_port = htons(DEFAULT_PORT);if (bind(listen_fd,(struct sockaddr*)&servaddr,sizeof(servaddr))== -1){printf("bind socket error: %s(errno: %d)\n", strerror(errno), errno);closesocket(listen_fd);exit(0);}if (listen(listen_fd, 10) == -1){printf("listen socket error: %s(errno: %d)\n", strerror(errno), errno);closesocket(listen_fd);exit(0);}accept_fds.clear();while (1){prepareIDs(listen_fd, accept_fds, max_fd, readfds, writefds);//printf("r1: readfds.fd_count[%d],writefds.fd_count[%d]\n", readfds.fd_count, writefds.fd_count);int rtn = select(max_fd, &readfds, &writefds, 0, &timeout);//printf("r2: readfds.fd_count[%d],writefds.fd_count[%d]\n", readfds.fd_count, writefds.fd_count);if (FD_ISSET(listen_fd, &readfds))//如果listen_fd有值,代表有新的链接,存入新的socketid{int new_socket = accept(listen_fd, (struct sockaddr*)NULL,NULL);printf("receive client accept\n");if (new_socket<0){printf("accept socket error: %s(errno: %d)", strerror(errno), errno);continue;}accept_fds.push_back(new_socket);}for (auto itor = accept_fds.begin(); itor != accept_fds.end(); itor++){if (FD_ISSET(*itor, &readfds))doReadActions(*itor);if (FD_ISSET(*itor, &writefds))doWriteActions(*itor);}}return 0;}
客户端代码如下:
#include <Winsock2.h>#include <stdio.h>#pragma comment(lib, "ws2_32.lib") #pragma message("error!!!")#define DefaultPort 48000void main(){WORD wVersionRequested;WSADATA wsaData;int err;wVersionRequested = MAKEWORD( 2, 2 );err = WSAStartup( wVersionRequested, &wsaData );if ( err != 0 ) {return;}SOCKET sockClient=socket(AF_INET,SOCK_STREAM,0);SOCKADDR_IN addrSrv;addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");addrSrv.sin_family=AF_INET;addrSrv.sin_port=htons(DefaultPort);connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));send(sockClient,"This is test",strlen("This is test")+1,0);char recvBuf[100];memset(recvBuf,0,sizeof(recvBuf));while(recv(sockClient,recvBuf,100,0)>0){printf("%s\n",recvBuf);}//recv(sockClient,recvBuf,100,0);//printf("%s\n",recvBuf);closesocket(sockClient);WSACleanup();}



0 0