- 论坛徽章:
- 0
|
本帖最后由 setsuna 于 2010-05-20 19:20 编辑
server端运行在linux下,使用单线程+ select多路复用模型。client运行在win下。client发送命令来通知server,server返回数据给client。
遇到的问题: 比如server端listen的backlog为5,那么client在连接4次之后就会出现:可以连接server,但是客户端发送数据给server,server端select总是返回0并且不会返回数据给client。
请问是代码哪里出了错?万分感谢!
代码大致如下:- //创建侦听Socket
- if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
- {
- perror("Create listening socket error!");
- exit(1);
- }
-
- int flags;
- if(flags= fcntl(sock_fd, F_GETFL, 0) <0)
- {
- printf("F_GETFL errors, %s\n", strerror(errno));
- return -1;
- }
- flags |= O_NONBLOCK;
- if(flags= fcntl(sock_fd, F_SETFL, 0) <0)
- {
- printf("F_SETFL O_NONBLOCK errors, %s\n", strerror(errno));
- return -1;
- }
- //配置侦听Socket
- //SO_REUSEADDR BOOL 允许套接口和一个已在使用中的地址捆绑。
- if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
- {
- perror("setsockopt error!");
- exit(1);
- }
-
- server_addr.sin_family = AF_INET; // host byte order
- server_addr.sin_port = htons(MYPORT); // short, network byte order
- server_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
- memset(server_addr.sin_zero, '\0', sizeof(server_addr.sin_zero));
- //绑定新创建的Socket到指定的IP和端口
- if (bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1)
- {
- perror("bind error!");
- exit(1);
- }
- //开始侦听,最大连接数为BACKLOG
- if (listen(sock_fd, BACKLOG) == -1)
- {
- perror("listen error!");
- exit(1);
- }
-
- //监控文件描述符集合
- fd_set fdsr;
- //监控文件描述符集合中最大的文件号
- int maxsock;
- //Select超时返回的时间。
- struct timeval tv;
- conn_amount = 0;
- sin_size = sizeof(client_addr);
- maxsock = sock_fd;
- for(i = 0; i< BACKLOG; i++)
- {
- fd_A[i] = -1;
- }
- // 初始化文件描述符集合 initialize file descriptor set
- FD_ZERO(&fdsr);
- // 把Sock_fd加入到文件描述符集合
- FD_SET(sock_fd, &fdsr);
- while (1)
- {
- // 超时设置30秒
- tv.tv_sec = 30;
- tv.tv_usec = 0;
- int nready = select(maxsock + 1, &fdsr, NULL, NULL, &tv);
- if (nready < 0)
- {
- perror("select error!");
- break;
- }
- else if (nready == 0)
- {
- printf("timeout\n");
- continue;
- }
- // 检查是否有新连接进来,如果有新连接进来,接收连接,生成新socket,
- //并加入到监控文件描述符集合中。
- if (FD_ISSET(sock_fd, &fdsr))
- {
- //接受连接
- new_fd = accept(sock_fd, (struct sockaddr *)&client_addr, &sin_size);
- if (new_fd <= 0)
- {
- perror("accept socket error!");
- continue;
- }
- for (i = 0; i < BACKLOG; i++)
- {
- if(fd_A[i] < 0)
- {
- fd_A[i] = new_fd;
- printf("new connection client[%d] %s:%d\n", conn_amount,inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
- break;
- }
- }
- if(i == BACKLOG)
- {
- printf("too many clients: %d\n", i);
- exit(0);
- }
- FD_SET(new_fd, &fdsr);
- if(new_fd > maxsock)
- maxsock = new_fd;
- if(maxi <i)
- maxi = i;
- if(--nready <= 0)
- continue;
- }
- int tmp_sock;
- // 轮询各个文件描述符(socket)
- for (i = 0; i <= maxi; i++)
- {
- //FD_ISSET(int fd, fdset *fdset):检查fdset联系的文件句柄fd是否可读写,
- printf("start\n");
- if((tmp_sock = fd_A[i]) <0)
- continue;
- // >0表示可读写。
- if (FD_ISSET(tmp_sock, &fdsr))
- {
- // 接收数据
- ret = recv(fd_A[i], buf, sizeof(buf), 0);
- if (ret <= 0) //接收数据出错
- {
- printf("client[%d] close\n", i);
- close(fd_A[i]);
- FD_CLR(fd_A[i], &fdsr);
- fd_A[i] = -1;
- }
- else // 数据接收成功
- {
- //返回数据,暂略!
- }
- if(--nready <= 0)
- continue;
- }
- }
- }
复制代码 |
|