C++ Socket通讯连接Server,并可设置连接超时时间

Socket通讯连接Server,并可设置连接超时时间

非阻塞模式:使用 ioctlsocket 将 socket 设置为非阻塞模式,这样 connect 调用不会阻塞主线程。

连接线程:在一个新线程中执行连接操作,使用 std::atomic 来检查连接是否成功。

超时逻辑:主线程使用一个循环来检查连接是否成功,若超出设定的超时时间则退出。

cpp 复制代码
#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <thread>
#include <atomic>

#pragma comment(lib, "ws2_32.lib")


void ThreadConnect(SOCKET sock, struct sockaddr_in* server, std::atomic<bool>& connected)
{
    if (connect(sock, (struct sockaddr*)server, sizeof(*server)) == SOCKET_ERROR)
    {
        connected = false;
    }
    else
    {
        connected = true;
    }
}

bool ConnectServer()
{
    WSADATA wsaData;
    SOCKET sock;
    struct sockaddr_in server;

    // 初始化 Winsock
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    {
        std::cerr << "Failed to initialize Winsock. Error: " << WSAGetLastError() << std::endl;
        return false;
    }

    // 创建 socket
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == INVALID_SOCKET)
    {
        std::cerr << "Could not create socket. Error: " << WSAGetLastError() << std::endl;
        WSACleanup();
        return false;
    }

    // 设置 socket 为非阻塞模式
    u_long mode = 1; // 1 表示非阻塞模式
    ioctlsocket(sock, FIONBIO, &mode);

    // 配置服务器地址
    server.sin_family = AF_INET;
    server.sin_port = htons(7999); // 服务器端口
    inet_pton(AF_INET, "127.0.0.1", &server.sin_addr); // 服务器地址

    std::atomic<bool> connected(false);
    std::thread connectThread(ThreadConnect, sock, &server, std::ref(connected));

    // 等待连接或超时
    int connecTimeout = 1000;

    DWORD startTime = GetTickCount();
    while (GetTickCount() - startTime < connecTimeout)
    {
        if (connected)
        {
            break;
        }
        Sleep(100);
    }   
    connectThread.join(); // 关闭连接线程

    std::cout << "Connection time: " << (GetTickCount() - startTime) << " ms" << std::endl;

    if (!connected)
    {
        std::cerr << "Connection timeout." << std::endl;
        closesocket(sock);
        WSACleanup();

        return false;
    }

    mode = 0; // 设置为阻塞模式
    ioctlsocket(sock, FIONBIO, &mode);

    std::cout << "Connected to server!" << std::endl;


    int sendTimeout = 1000; // 发送超时设置
    int recvTimeout = 1000; // 接收超时设置

    if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (const char*)&sendTimeout, sizeof(sendTimeout)) < 0)
    {
        std::cerr << "Failed to set send timeout. Error: " << WSAGetLastError() << std::endl;
        closesocket(sock);
        WSACleanup();
        return false;
    }

    if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&recvTimeout, sizeof(recvTimeout)) < 0)
    {
        std::cerr << "Failed to set receive timeout. Error: " << WSAGetLastError() << std::endl;
        closesocket(sock);
        WSACleanup();
        return false;
    }

    // 这里可以添加发送和接收数据的代码

    // 关闭 socket
    closesocket(sock);
    WSACleanup();

    return true;
}

int main()
{

    ConnectServer();

    std::cin.get();

    return 0;
}
相关推荐
虾球xz4 小时前
游戏引擎学习第268天:合并调试链表与分组
c++·学习·链表·游戏引擎
fpcc5 小时前
跟我学c++高级篇——模板元编程之十三处理逻辑
c++
格林威5 小时前
Baumer工业相机堡盟工业相机的工业视觉中为什么偏爱“黑白相机”
开发语言·c++·人工智能·数码相机·计算机视觉
Dream it possible!6 小时前
LeetCode 热题 100_只出现一次的数字(96_136_简单_C++)(哈希表;哈希集合;排序+遍历;位运算)
c++·leetcode·位运算·哈希表·哈希集合
Dddle17 小时前
C++:this指针
java·c语言·开发语言·c++
不見星空8 小时前
2025年第十六届蓝桥杯软件赛省赛C/C++大学A组个人解题
c语言·c++·蓝桥杯
jiunian_cn8 小时前
【c++】异常详解
java·开发语言·数据结构·c++·算法·visual studio
梁下轻语的秋缘8 小时前
每日c/c++题 备战蓝桥杯(洛谷P1387 最大正方形)
c语言·c++·蓝桥杯
熬夜学编程的小王8 小时前
【C++进阶篇】多态
c++·多态·静态绑定与动态绑定
UpUpUp……9 小时前
Linux--JsonCpp
linux·运维·服务器·c++·笔记·json