思路:使用mfc SOCKET类创建客户端socket,在创建方式和连接之间进行保活模式添加,话不多说代码如下,本人模拟按键点击开启定时器进行创建以及连接:
void CVSPCDemoDlg::OnBnClickedButton() // 创建TCPclient套接字
{
// TODO: 在此添加控件通知处理程序代码
// 模式选择,选择连接模式
CString m_choose;
m_choose.GetWindowText(data_choose); // 获取模式选择
if(data_choose == "TCP Client")
{
SetTimer(1,2000, NULL); // 启动定时器,继续触发定时器消息
}
}
void CVSPCDemoDlg::OnTimer(UINT_PTR nIDEvent) // 添加定时器函数
{
if (nIDEvent == 1) // 定时器1
{
// TODO: 处理定时器事件
sock = socket(AF_INET,SOCK_STREAM,0);//创建套接字(socket)
WSADATA wsaData;
WORD wVersion;
wVersion = MAKEWORD(2, 2);
WSAStartup(wVersion, &wsaData);
CString serial_port;
m_comboPortName.GetWindowText(serial_port); // 获取所应用的虚拟串口名称
CString data_ip;
m_IP_edit.GetWindowText(data_ip);
CString data_port;
m_PORT_edit.GetWindowText(data_port);
int data_port_1 = atoi(data_port);
server_addr.sin_addr.s_addr = inet_addr(data_ip); // 目的IP
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(data_port_1); // 目的端口
if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) { // 创建tcp套接字
MessageBox("创建套接字失败!");
return;
}
// 设置 TCP 保活选项
int keepAlive = 1; // 开启 TCP 保活功能
int keepIdle = 60; // 空闲时间为 60 秒
int keepInterval = 10; // 每次发送探测包的间隔为 10 秒
int keepCount = 3; // 最多发送 3 次探测包
int nRet = setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, reinterpret_cast<const char*>(&keepAlive), sizeof(keepAlive));
if (nRet == SOCKET_ERROR) {
int nErrCode = WSAGetLastError();
CString strMsg;
strMsg.Format(_T("setsockopt failed with error code: %d"), nErrCode);
//AfxMessageBox(strMsg);
} else {
//AfxMessageBox(_T("setsockopt succeeded"));
}
setsockopt(sock, IPPROTO_TCP, TCP_KEEPALIVE, reinterpret_cast<const char*>(&keepIdle), sizeof(keepIdle));
CString data_port_2;
m_PORT_edit.GetWindowText(data_port_2); // 获取目的端口
if (connect(sock, (struct sockaddr *) &server_addr, sizeof(SOCKADDR_IN)) == SOCKET_ERROR) { // 进行tcp连接
// (连接失败)
return;
}else {
// (连接成功)
KillTimer(1); // 杀死第一个定时器
}
}
CDialog::OnTimer(nIDEvent);
}
可以在连接成功部分创建一个线程进行接收使用,如果在限定时间服务器若是死掉,那么在客户端的recv返回值就会为-1。