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

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/yishuihan1212/article/details/53667272

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 4096

void 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 48000

void 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();
	
}



猜你喜欢

转载自blog.csdn.net/yishuihan1212/article/details/53667272
今日推荐