客户端长连接断线重连机制
作者:互联网
// testsocketclient.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <winsock2.h> #include <stdio.h> #include <mstcpip.h> #pragma comment(lib, "Ws2_32.lib") SOCKET sockClient = 0; static int conn_status = 0; #define IP_ADDRESS ("192.168.207.131") #define PORT (9099) #include <iostream> using namespace std; int socket_tcp_alive(int socket) { int ret = 0; int keep_alive = 1; ret = setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&keep_alive, sizeof(keep_alive)); if (ret == SOCKET_ERROR) { printf("setsockopt failed: %d \n", WSAGetLastError()); return -1; } struct tcp_keepalive in_keep_alive = { 0 }; unsigned long ul_in_len = sizeof(struct tcp_keepalive); struct tcp_keepalive out_keep_alive = { 0 }; unsigned long ul_out_len = sizeof(struct tcp_keepalive); unsigned long ul_bytes_return = 0; in_keep_alive.onoff = 1; /*打开keepalive*/ in_keep_alive.keepaliveinterval = 5000; /*发送keepalive心跳时间间隔-单位为毫秒*/ in_keep_alive.keepalivetime = 1000; /*多长时间没有报文开始发送keepalive心跳包-单位为毫秒*/ ret = WSAIoctl(socket, SIO_KEEPALIVE_VALS, (LPVOID)&in_keep_alive, ul_in_len, (LPVOID)&out_keep_alive, ul_out_len, &ul_bytes_return, NULL, NULL); if (ret == SOCKET_ERROR) { printf("WSAIoctl failed: %d \n", WSAGetLastError()); return -1; } return 0; } int tcp_connect_server() { int save_errno; SOCKADDR_IN server_addr; conn_status = 0; memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = inet_addr(IP_ADDRESS); server_addr.sin_port = htons(PORT); sockClient = ::socket(PF_INET, SOCK_STREAM, 0); if (sockClient == -1) return sockClient; conn_status = ::connect(sockClient, (struct sockaddr*)&server_addr, sizeof(server_addr)); if (conn_status == -1) { save_errno = errno; //清理 closesocket(sockClient); errno = save_errno; //the close may be error return -1; } // evutil_make_socket_nonblocking(sockfd); return sockClient; } DWORD WINAPI monitorThread(LPVOID pM) { while (1) { char szRecvBuf[10] = { 0 }; // send(sockClient, "this is qiang ge1233", strlen("this is qiang ge1234") + 1, 0); int nRet = recv(sockClient, szRecvBuf, 1, MSG_PEEK); // 注意, 最后一个参数必须是MSG_PEEK, 否则会影响主线程接收信息 if (nRet <= 0) { printf("监测到啦: nRet is %d\n", nRet); closesocket(sockClient); sockClient = NULL; sockClient = tcp_connect_server(); if (conn_status != -1) socket_tcp_alive(sockClient); // break; } Sleep(5000); } return 0; } void main() { //加载套接字库,版本协商 WORD wVersionRequired; WSADATA wsaData; int err; int status, save_errno; //请求库 //WSAStartup( WORD wVersionRequired, WSADATA lpWSAData ); wVersionRequired = MAKEWORD(1, 1); err = WSAStartup(wVersionRequired, &wsaData); if (err != 0) { //不等于0就退出 return; } //高字节和低字节都不为1 if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) { WSACleanup(); return; } sockClient = socket(AF_INET, SOCK_STREAM, 0); //设定服务器的地址信息 SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr = inet_addr(IP_ADDRESS); addrSrv.sin_family = AF_INET; addrSrv.sin_port = htons(PORT); while (1) { conn_status = connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)); if (conn_status == -1) { save_errno = errno; //清理 errno = save_errno; //the close may be error Sleep(3000); cout << "one lian test" << endl; continue; } else { socket_tcp_alive(sockClient); break; } } HANDLE handle = CreateThread(NULL, 0, monitorThread, NULL, 0, NULL); // send(sockClient, "this is qiang ge", strlen("this is qiang ge") + 1, 0); getchar(); closesocket(sockClient); WSACleanup(); system("PAUSE"); }
标签:return,addr,sockClient,alive,keep,断线,重连,server,客户端 来源: https://www.cnblogs.com/hshy/p/10991323.html