- 论坛徽章:
- 0
|
socket连接成功后,由非阻塞转为阻塞之后,select得到可读,可是读的时候没有读到数据,这是什么原因呢?
代码如下:
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/select.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <netdb.h>
- #include <errno.h>
- #include <string.h>
- #include <strings.h>
- #include <unistd.h>
- #include <fcntl.h>
- #define STATUS_OOS 0
- #define STATUS_CONNECTING 1
- #define STATUS_INSERVICE 2
- int main()
- {
- int status = STATUS_OOS;
- int sockfd = 0;
- int port = 8011;
- char host[] = "192.168.100.209";
-
- struct sockaddr_in serv_addr;
- struct hostent *hp;
- int setFlag;
- struct linger linger;
-
- int flags;
- if ( (hp = gethostbyname(host)) == NULL) {
- //perror ("sockTcpConnect:gethostbyname error ");
- printf("gethostbyname error host = '%s'\n",host);
- return 0;
- }
- bcopy(hp->h_addr, (char *) &serv_addr.sin_addr, hp->h_length);
- if ( (sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0 ) {
- perror ("generate socket error ");
- return 0;
- }
- bzero((char *)&serv_addr, sizeof(serv_addr));
- serv_addr.sin_family = AF_INET;
- memcpy (&serv_addr.sin_addr, hp->h_addr, hp->h_length);
- serv_addr.sin_port = htons(port);
- setFlag = 1;
- if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &setFlag, sizeof(setFlag)) < 0) {
- close(sockfd);
- return 0;
- }
- linger.l_onoff = 1;
- linger.l_linger = 0;
- if (setsockopt(sockfd, SOL_SOCKET, SO_LINGER, (char *) &linger, sizeof(linger)) < 0) {
- close(sockfd);
- return 0;
- }
- /***************************************************/
- //在connect之前,设成非阻塞模式
- flags = fcntl(sockfd, F_GETFL,0);
- fcntl(sockfd,F_SETFL, flags | O_NONBLOCK);
- /***************************************************/
- if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
- if(errno != EINPROGRESS){
- close(sockfd);
- return 0;
- }
- status = STATUS_CONNECTING;
- }
- else {
- status = STATUS_INSERVICE;
- }
- while(1) {
- fd_set fdread;
- fd_set fdwrite;
- struct timeval tvSelect;
- int n;
-
- FD_ZERO(&fdread);
- FD_ZERO(&fdwrite);
- FD_SET(sockfd, &fdread);
- tvSelect.tv_sec = 0;
- tvSelect.tv_usec = 500;
- if(STATUS_CONNECTING==status){
- fdwrite = fdread;
- }
-
- int retval = select(sockfd + 1, &fdread, status==STATUS_CONNECTING?&fdwrite:NULL, NULL, &tvSelect);
- if(retval < 0){
- if ( errno == EINTR ){
- printf("select error\n");
- continue;
- }
- else{
- printf("error\n");
- close(sockfd);
- return 0;
- }
- }
- else if(retval == 0){
- if(status == STATUS_CONNECTING){
- printf("select timeout, state CONNECTING, still connecting...\n");
- continue;
- }
- }
- else if((STATUS_CONNECTING==status) && ( FD_ISSET(sockfd, &fdread) || FD_ISSET(sockfd, &fdwrite) ) ){
- printf("no-block connnect select return, check socket.\n");
- int error;
- socklen_t len = sizeof(error);
- if(getsockopt(sockfd,SOL_SOCKET,SO_ERROR,&error,&len) < 0 || error != 0){
- printf("getsockopt return error, %d:%d\n", error, errno);
- close(sockfd);
- return 0;
- }
- else{
- printf("no-block connnect ok, set socket to block mode.\n");
- /***************************************************/
- //在connect成功之后,设成阻塞模式
- int flags = fcntl(sockfd, F_GETFL,0);
- flags &= ~O_NONBLOCK;
- fcntl(sockfd,F_SETFL, flags);
- /***************************************************/
- status = STATUS_INSERVICE;
- continue;
- }
- }
- else if((STATUS_INSERVICE==status)&& FD_ISSET(sockfd, &fdread)) {
- char recvbuf[10240];
- bzero(recvbuf, sizeof(recvbuf));
- n = read (sockfd, recvbuf, sizeof(recvbuf) - 1);
- printf("read data length is %d\n", n);
- //select返回可读,应该是不会读不到数据的,但收了几个消息之后,就会返回读取长度为0,不知道原因
- if(n == 0){
- close(sockfd);
- return 0;
- }
- else if (n < 0) {
- printf("read return<0, errno is %d\n", errno);
- if ( errno == EINTR ) {
- continue;
- }
- else {
- close(sockfd);
- return 0;
- }
- }
- //proc data......
- }
- }
- close(sockfd);
- return 1;
- }
复制代码
[ 本帖最后由 vafls_scott 于 2007-1-31 16:33 编辑 ] |
|