select无法检测到UDP socket可读,调用recvfrom却可以收到数据

LeeRockstone 发布于 2013/11/24 12:33
阅读 3K+
收藏 0

我在使用select监控UDPsocket的时候发现无法收到数据,就写了个程序测试一下,发现select总是在超时之后返回0,接着调用recvfrom却可以收到数据。麻烦各位大牛看看我哪里写的不对。

// server
int main(int argc, char *argv[]){
	struct sockaddr_in s_addr;
	struct sockaddr_in c_addr;
	s_addr.sin_family = AF_INET;
	s_addr.sin_port = htons(9999);
	s_addr.sin_addr.s_addr = htonl(INADDR_ANY);

	int fd = socket(AF_INET, SOCK_DGRAM, 0);
	if(fd == -1){
		printf("socket err\n");
		return -1;
	}
	
	if(bind(fd, (struct sockaddr *)&s_addr, sizeof(s_addr)) == -1){
		fprintf(stderr, "%s\n", "bing port error\n");
		return -1;
	}
	int n;
	fd_set 	read_set;
	fd_set  write_set;
       fd_set  err_set;
	while(true){
		FD_ZERO(&read_set);
		FD_ZERO(&write_set);
                FD_ZERO(&err_set);
		FD_SET(fd, &read_set);
		FD_SET(fd, &write_set);
                FD_SET(fd, &err_set);

		struct timeval 	tv;
		tv.tv_sec = 0;
		tv.tv_usec = 2000 * 1000;

		int ret = select(2, &read_set, &write_set, &err_set, &tv);
		printf("select return=%d\n", ret);
		char sz[32];
		socklen_t c_addr_len = (socklen_t)sizeof(c_addr);
		n = recvfrom(fd, sz, 32, 0, (struct sockaddr *)&c_addr, &c_addr_len);
		printf("select ret=%d,recv %s\n", ret, sz);

		if(ret < 0)
			printf("select err\n");
		else if(ret > 0){
			if(FD_ISSET(fd, &read_set)){
				char buf[32] = {0};
				n = read(fd, buf, 31);
				printf("recv n=%d\n", n);
				printf("%s\n", buf);
			}
			if(FD_ISSET(fd, &write_set)){
				printf("ret=%d\n", ret);
			}
		}
		usleep(200);
	}
	return 0;
}


客户端比较简单,一直对本机9999端口发数据。 我是在虚拟机ubuntu上运行的程序,select每次都返回0,recvfrom却可以收到数据,netstat 可以看到接收队列里有数据变化,不知道是哪里写的不对。
加载中
0
开源中国精神科主任
开源中国精神科主任
linux下
int select(int nfds, fd_set *readfds, fd_set *writefds,
                  fd_set *exceptfds, struct timeval *timeout);



第一个参数是有用的,表示最大的文件描述符加1,所以你把它设大一点试试

LeeRockstone
LeeRockstone
谢谢啦,我理解错误把select第一个参数设错了~
返回顶部
顶部