本文共 2683 字,大约阅读时间需要 8 分钟。
BSD
int connectTimeout = 30;setsockopt(sock, IPPROTO_TCP, TCP_CONNECTIONTIMEOUT,(char *)&connectTimeout, sizeof(connectTimeout));Linux socket选项TCP_SYNCNT可以控制TCP连接SYN重传次数,默认为0,为0时SYN重传次数由系统参数 net.ipv4.tcp_syn_retries 控制,该系统参数默认值为6。
SYN重传次数影响connect超时时间,当重传次数为6时,超时时间为1+2+4+8+16+32+64=127秒。
int syncnt = 4;setsockopt(sock, IPPROTO_TCP, TCP_SYNCNT, &syncnt, sizeof(syncnt));使用select(Windows,Linux,BSD都可以用) 创建socket,将socket设置为非阻塞模式。 调用connect连接,如果能立即连接则返回0,不能立即连接返回-1,这个时候判断错误码是否表示暂时不能完成,是的话继续下一步。 接着调用select()在指定的时间内检测socket是否可写,如果可写表明connect()连接成功,0表示超时,-1表示出现了错误。 windows下代码:
void attemptConnect(const char* ip,unsigned short port,int timeout){ //初始化 WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != NO_ERROR) { printf("WSAStartup function failed\n"); return; } SOCKET connectSocket= INVALID_SOCKET; do { //创建socket connectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (connectSocket == INVALID_SOCKET) { printf("socket function failed with error: %ld\n", WSAGetLastError()); break; } //socket设置为非阻塞 unsigned long on = 1; if (ioctlsocket(connectSocket, FIONBIO, &on) < 0) { printf("ioctlsocket failed\n"); break; } //尝试连接 sockaddr_in clientService; clientService.sin_family = AF_INET; clientService.sin_addr.s_addr = inet_addr(ip); clientService.sin_port = htons(port); int ret = connect(connectSocket, (struct sockaddr*)&clientService, sizeof(clientService)); if (ret == 0) { printf("connect success1\n"); return; } //因为是非阻塞的,这个时候错误码应该是WSAEWOULDBLOCK,Linux下是EINPROGRESS if (ret < 0 && WSAGetLastError() != WSAEWOULDBLOCK) { printf("connect failed with error: %ld\n", WSAGetLastError()); return; } fd_set writeset; FD_ZERO(&writeset); FD_SET(connectSocket, &writeset); timeval tv; tv.tv_sec = timeout; tv.tv_usec = 0; ret = select(connectSocket + 1, NULL, &writeset, NULL, &tv); if (ret == 0) { printf("connect timeout\n"); } else if (ret < 0) { printf("connect failed with error: %ld\n", WSAGetLastError()); } else { printf("connect success2\n"); } } while (false); if (connectSocket != INVALID_SOCKET) { closesocket(connectSocket); } WSACleanup();} int main(){ attemptConnect("127.0.0.1",80,15); system("pause"); return 0;}
————————————————
版权声明:本文为CSDN博主「土豆吞噬者」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/xiongya8888/article/details/96996236