使用 select 设计超时 connect 函数的问题(linux 上连接 127.0.0.1 任何端口总是成功)
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <time.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
int fd, retval;
struct sockaddr_in addr;
struct timeval timeo = {3, 0};
socklen_t len = sizeof(timeo);
fd_set set;
fd = socket(AF_INET, SOCK_STREAM, 0);
if (argc == 4) timeo.tv_sec = atoi(argv[3]);
int savefl = fcntl(fd,F_GETFL);
fcntl(fd, F_SETFL, savefl | O_NONBLOCK);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(argv[1]);
addr.sin_port = htons(atoi(argv[2]));
printf( "%d\n ", time(NULL));
if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == 0)
{
close(fd);
printf( "connected..1\n ");
return 0;
}
if (errno != EINPROGRESS)
{
close(fd);
perror( "connect..2 ");
return -1;
}
FD_ZERO(&set);
FD_SET(fd, &set);
retval = select(fd + 1, NULL, &set, NULL, &timeo);
if (retval == -1)
{
close(fd);
perror( "select ");
return -1;
}
else if(retval == 0)
{
close(fd);
fprintf(stderr, "timeout\n ");
printf( "%d\n ", time(NULL));
return 0;
}
printf( "connected .. 3\n ");
fcntl(fd, F_SETFL,savefl);
close(fd);
return 0;
}
1. OS:linux kenerl 2.6 (fedora.unix-center.net)
2. 测试连接 (202.108.22.43:80,202.108.22.43:8000,) 百度,程序正常,其他机器也正常
3. 但是测试 127.0.0.1 任何端口都说能连接上,非常奇怪
[解决办法]
用netstat看是连上的么?
[解决办法]
fcntl(fd, F_SETFL, savefl | O_NONBLOCK);
//你把他设置成非阻塞方式啦,
你的判断方式有点问题:
if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == 0)//成功就退出?那下面的其他代码都是在连接失败情况下的处理,有何意义?
{
close(fd);
printf( "connected..1\n ");
return 0;
}
[解决办法]
retval = select(fd + 1, NULL, &set, NULL, &timeo);
retval=1的候未必接得上,
retval=1得候要判errno的值是不是0
[解决办法]
retval=1
是很正常, 比如你要connect的候3次握手
connect的候基本就可以建立成功了
但是一特例就是有firewall阻的connect依然去write
你的可以通抓取packet解.