user-0 提问: read被阻塞了，莫名其妙，求帮忙

回复:
user: user-0
content: 代码如下： void *socthread() { 		timeout.tv_sec = 3;         timeout.tv_usec = 0; 		while(1) 		{ 			printf("\nSpiMaster_V35: create socket");fflush(stdout); 			 			if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) 			{                           //调用socket创建用于监听客户端的socket 				printf("\nSpiMaster_V35: create socket failed");fflush(stdout); 				exit(1); 			}  			int opt = SO_REUSEADDR; 			setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));  //设置socket属性  			 			int flags = fcntl(listenfd, F_GETFL, 0); 			fcntl(listenfd, F_SETFL, flags|O_NONBLOCK); 			 			bzero(&server, sizeof(server)); 			server.sin_family = AF_INET; 			server.sin_port = htons(20002); 			server.sin_addr.s_addr = htonl(INADDR_ANY);  			printf("\nSpiMaster_V35: bind");fflush(stdout); 			 			if (bind(listenfd, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1) 			{                           //调用bind绑定地址 				printf("\nSpiMaster_V35: Bind error.");fflush(stdout); 				exit(1); 			}  			printf("\nSpiMaster_V35: listen");fflush(stdout); 			 			if (listen(listenfd, BACKLOG) == -1) 			{                           //调用listen开始监听 				printf("\nSpiMaster_V35: listen() error\n");fflush(stdout); 				exit(1); 			}  			printf("\nSpiMaster_V35: listen end");fflush(stdout); 			 			//初始化select 			maxfd = listenfd; 			maxi = -1; 			for (i = 0; i < FD_SETSIZE; i++) 			{ 				client[i].fd = -1; 			} 			FD_ZERO(&allset);           //清空 			FD_SET(listenfd, &allset);  //将监听socket加入select检测的描述符集合 			//printf("\nspi_master: loop start");fflush(stdout); 			while (1) 			{ 				usleep(10000); 				//processMonWrite(MON_TCP_SERVER_FLAG, TcpSemId, PShmBuf); 				struct sockaddr_in addr; 				rset = allset; 				//printf("\nspi_master: begin select。。。。。。");fflush(stdout); 				nready = select(maxfd + 1, &rset, NULL, NULL, &timeout);    //调用select 				 				if (nready == -1) 				{ 					//select错误，退出程序  					printf("\nspi_master_V35: Select() error, exit(%d).", nready);fflush(stdout); 					break; 				} 				else if (nready == 0) 				{ 					//再次轮询 					//printf("\nspi_master: Select() NG, continue(%d).", nready);fflush(stdout); 					continue; 				} 				else 				{ 					//printf("\nspi_master: Select() OK", nready);fflush(stdout); 				}  				 				if (FD_ISSET(listenfd, &rset)) 				{                       //检测是否有新客户端请求 					printf("\nspi_master_V35: Accept a connection.\n");fflush(stdout); 					//调用accept，返回服务器与客户端连接的socket描述符 					sin_size = sizeof(struct sockaddr_in); 					if ((connectfd = 						 accept(listenfd, (struct sockaddr *)&addr, (socklen_t *) & sin_size)) == -1) 					{ 						printf("\nspi_master_V35: Accept() error\n");fflush(stdout); 						continue; 					}  					flagsclient = fcntl(connectfd, F_GETFL, 0);         			fcntl(connectfd, F_SETFL, flagsclient|O_NONBLOCK);  					//将新客户端的加入数组 					for (i = 0; i < FD_SETSIZE; i++) 					{  						if (client[i].fd < 0) 						{ 							char buffer[20]; 							client[i].fd = connectfd;   //保存客户端描述符 							clientfd = connectfd; 							memset(buffer, '0', sizeof(buffer)); 							sprintf(buffer, "Client[%.2d]", i); 							memcpy(client[i].name, buffer, strlen(buffer)); 							client[i].addr = addr; 							memset(buffer, '0', sizeof(buffer)); 							sprintf(buffer, "Only For Test!"); 							memcpy(client[i].data, buffer, strlen(buffer)); 							printf(" spi_master: Add a new connection. clientid=%d\n",connectfd); 							printf("\nSocket clientfd=%d.\n",clientfd);fflush(stdout); 							fflush(stdout); 							break; 						} 					} 					 					if (i == FD_SETSIZE) 						printf("\nSpiMaster_V35: Too many clients\n");fflush(stdout); 					FD_SET(connectfd, &allset); //将新socket连接放入select监听集合 					if (connectfd > maxfd) 						maxfd = connectfd;  //确认maxfd是最大描述符 					if (i > maxi)       //数组最大元素值 						maxi = i; 					if (--nready <= 0) 						continue;       //如果没有新客户端连接，继续循环 				} 				 				for (i = 0; i <= maxi; i++) 				{ 					//shi 600 S 					//processMonWrite(MON_TCP_SERVER_FLAG, TcpSemId, PShmBuf); 					 					if ((sockfd = client[i].fd) < 0)    //如果客户端描述符小于0，则没有客户端连接，检测下一个 						continue; 					if(client[i].fd != clientfd) 					    continue; 					// 有客户连接，检测是否有数据 					if (FD_ISSET(sockfd, &rset)) 					{ 						printf("\nTCPServer: Receive from connect fd[%d].\n", client[i].fd);fflush(stdout); 						memset(recvbuf, 0, MAX_DATA_SIZE); 						if ((n = read(sockfd, recvbuf, READ_BUF_SIZE)) == 0) 						{               //从客户端socket读数据，等于0表示网络中断 						    printf("\n fd close.fd=%d,errno=%d\n",sockfd,errno); 							close(sockfd);  //关闭socket连接 							FD_CLR(sockfd, &allset);    //从监听集合中删除此socket连接 							client[i].fd = -1;  //数组元素设初始值，表示没客户端连接 						} 						else 							readinfo(&client[i], recvbuf, n); //接收到客户数据，开始处理 						//if (--nready <= 0) 						//    break;      //如果没有新客户端有数据，跳出for循环回到while循环 					} 				} 				 			} 			close(listenfd); 	    } }

user: user-0
content: 各位，我把clientfd设置成非阻塞的，然后运行1天左右，还是会阻塞，同时客户端write也失败了并且错误码是11

user: user-1
content: 引用 1 楼 hnwyllmm 的回复:clientfd，楼主你的这个套接字没有设置非阻塞模式啊 select仅在可读或timeout时返回，如果不是timeout, 此时去read不应该阻塞（socket可以使block的）。 会不会是被其他线程读取了？

user: user-2
content: 楼上正解。不过干嘛要用非阻塞呢，没数据时就在那等着呗

user: user-3
content: 引用 5 楼 ufotree 的回复:谢谢各位回复， accept获得的fd在linux下默认是阻塞的吗？ 是

user: user-3
content: 引用 2 楼 ufotree 的回复:clientfd是客户端连过来的fd，这个怎么设置非阻塞？ 跟设置listenfd的方法一样的，调用一下就好了

user: user-4
content: 你的select使用有点问题吧，或者全部代码帖来可分析，select 在读取数据是不会阻塞的，但需要while循环设置socket到fd_set

user: user-5
content: 你发现阻塞了就说明是的  亲，像这种问题，自己试一下就出来了，我觉得比问出答案更好

user: user-0
content: 谢谢各位回复， accept获得的fd在linux下默认是阻塞的吗？

user: user-5
content: 引用 2 楼 ufotree 的回复:clientfd是客户端连过来的fd，这个怎么设置非阻塞？   不是select listensocket么，当有FD_ACCEPT 的时候就accpet 不就得到客户端socket了？ 然后就  cntl(clientfd, F_SETFL, flags|O_NONBLOCK);

user: user-6
content: 楼主你只是把listenfd设置为非阻塞，但对于真正用来接收数据的套接字clientfd却没有设置成非阻塞。

user: user-0
content: clientfd是客户端连过来的fd，这个怎么设置非阻塞？

user: user-3
content: clientfd，楼主你的这个套接字没有设置非阻塞模式啊