windows TCP Server demo

windows Webrtc +VS2019 (M124)下载编译以及调通测试demo windows webrtc 下载编译 阅读详情

TcpServer.h

#ifndef TCPSERVER_H
#define TCPSERVER_H

#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <vector>
#include <map>
#include <string>
#include <ctime>

// 引入静态链接库
#pragma comment(lib, "ws2_32.lib")

class TcpServer {
public:
    TcpServer();
    ~TcpServer();

    // 启动服务器,监听指定端口
    bool start(int port);

    // 停止服务器
    void stop();

    // 发送数据给指定客户端
    int sendData(SOCKET clientSocket, const char* data, int dataLength);

    // 处理服务器业务逻辑,通常在循环中调用
    void handle();

private:
    SOCKET listenSocket;
    std::vector<SOCKET> clientSockets;
    std::map<SOCKET, std::time_t> clientLastHeartbeatTime;
    int heartbeatInterval;  // 心跳包间隔时间(秒)

    // 设置套接字为非阻塞模式
    bool setSocketNonBlocking(SOCKET socket);

    // 接受新的客户端连接
    void acceptNewClients();

    // 接收客户端数据
    void receiveClientData();

    // 发送心跳包给客户端,并检测客户端响应
    void sendHeartbeatsAndCheck();

    // 移除已断开连接的客户端
    void removeDisconnectedClients();
};

#endif

TcpServer.cpp

#include "TcpServer.h"

// 构造函数,初始化相关成员变量
TcpServer::TcpServer() : listenSocket(INVALID_SOCKET), heartbeatInterval(5) {
    WSADATA wsaData;
    int result = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (result != 0) {
        std::cerr << "WSAStartup failed: " << result << std::endl;
    }
}

// 析构函数,关闭套接字并清理WinSock环境
TcpServer::~TcpServer() {
    stop();
    WSACleanup();
}

// 启动服务器,监听指定端口
bool TcpServer::start(int port) {
    listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (listenSocket == INVALID_SOCKET) {
        std::cerr << "Socket creation failed: " << WSAGetLastError() << std::endl;
        return false;
    }

    if (!setSocketNonBlocking(listenSocket)) {
        std::cerr << "Failed to set listen socket non-blocking" << std::endl;
        closesocket(listenSocket);
        return false;
    }

    sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = INADDR_ANY;
    serverAddr.sin_port = htons(port);
    int result = bind(listenSocket, (sockaddr*)&serverAddr, sizeof(serverAddr));
    if (result == SOCKET_ERROR) {
        std::cerr << "Bind failed: " << WSAGetLastError() << std::endl;
        closesocket(listenSocket);
        return false;
    }

    result = listen(listenSocket, SOMAXCONN);
    if (result == SOCKET_ERROR) {
        std::cerr << "Listen failed: " << WSAGetLastError() << std::endl;
        closesocket(listenSocket);
        return false;
    }

    return true;
}

// 停止服务器
void TcpServer::stop()
{
    if (listenSocket != INVALID_SOCKET) {
        closesocket(listenSocket);
        listenSocket = INVALID_SOCKET;
    }

    for (SOCKET clientSocket : clientSockets) {
        closesocket(clientSocket);
    }
    clientSockets.clear();
    clientLastHeartbeatTime.clear();
}

// 设置套接字为非阻塞模式
bool TcpServer::setSocketNonBlocking(SOCKET socket) {
    u_long iMode = 1;
    int result = ioctlsocket(socket, FIONBIO, &iMode);
    if (result == SOCKET_ERROR) {
        std::cerr << "ioctlsocket failed: " << WSAGetLastError() << std::endl;
        return false;
    }
    return true;
}

// 发送数据给指定客户端
int TcpServer::sendData(SOCKET clientSocket, const char* data, int dataLength) {
    if (clientSocket == INVALID_SOCKET) 
    {
        std::cerr << "Invalid client socket, cannot send data" << std::endl;
        return SOCKET_ERROR;
    }

    int totalBytesSent = 0;
    while (totalBytesSent < dataLength) 
    {
        int bytesSent = ::send(clientSocket, data + totalBytesSent, dataLength - totalBytesSent, 0);
        if (bytesSent == SOCKET_ERROR)
        {
            if (WSAGetLastError() == WSAEWOULDBLOCK) 
            {
                // 暂时无法发送,等待下次尝试
                continue;
            }
            return SOCKET_ERROR;
        }
        totalBytesSent += bytesSent;
    }
    return totalBytesSent;
}

// 接受新的客户端连接
void TcpServer::acceptNewClients() {
    SOCKET newClientSocket = accept(listenSocket, NULL, NULL);
    if (newClientSocket == INVALID_SOCKET) {
        if (WSAGetLastError() != WSAEWOULDBLOCK) {
            std::cerr << "Accept failed: " << WSAGetLastError() << std::endl;
        }
        return;
    }

    if (!setSocketNonBlocking(newClientSocket)) {
        std::cerr << "Failed to set client socket non-blocking" << std::endl;
        closesocket(newClientSocket);
        return;
    }

    clientSockets.push_back(newClientSocket);
    clientLastHeartbeatTime[newClientSocket] = std::time(nullptr);
}

// 接收客户端数据
void TcpServer::receiveClientData()
{
    std::vector<SOCKET> socketsToRemove;
    for (size_t i = 0; i < clientSockets.size(); ++i)
    {
        SOCKET clientSocket = clientSockets[i];
        char buffer[1024];
        int bytesReceived = ::recv(clientSocket, buffer, sizeof(buffer), 0);
        if (bytesReceived == SOCKET_ERROR) 
        {
            if (WSAGetLastError() == WSAEWOULDBLOCK) 
            {
                // 暂时无数据可读,继续检查下一个客户端
                continue;
            }
            socketsToRemove.push_back(clientSocket);
        }
        else if (bytesReceived == 0)
        {
            // 客户端关闭连接
            socketsToRemove.push_back(clientSocket);
        }
        else
        {
            buffer[bytesReceived] = '\0';
            std::string receivedData(buffer);
            // 在这里可以根据接收到的数据进行具体业务逻辑处理,比如解析命令等
            std::cout << "Received from client " << clientSocket << ": " << receivedData << std::endl;
            clientLastHeartbeatTime[clientSocket] = std::time(nullptr);
            std::string heartbeatData = "recv ok:";
            int sentBytes = sendData(clientSocket, heartbeatData.c_str(), heartbeatData.length());

        }
    }

    // 移除已断开连接的客户端(此处调用下面定义的 removeDisconnectedClients 函数,无参数传递)
    removeDisconnectedClients();
}

// 发送心跳包给客户端,并检测客户端响应
void TcpServer::sendHeartbeatsAndCheck()
{
    const char* heartbeatData = "HEARTBEAT";  // 简单的心跳包内容,可自定义
    int dataLength = strlen(heartbeatData);
    std::vector<SOCKET> socketsToRemove;
    for (auto& clientPair : clientLastHeartbeatTime) 
    {
        SOCKET clientSocket = clientPair.first;
        std::time_t& lastHeartbeatTime = clientPair.second;
        std::time_t currentTime = std::time(nullptr);
        if (currentTime - lastHeartbeatTime > heartbeatInterval) 
        {
            // 超过心跳间隔时间没收到心跳响应,认为客户端连接异常
            socketsToRemove.push_back(clientSocket);
            continue;
        }

        int sentBytes = sendData(clientSocket, heartbeatData, dataLength);
        if (sentBytes == SOCKET_ERROR) {
            // 发送心跳包失败,认为客户端连接可能有问题
            socketsToRemove.push_back(clientSocket);
            continue;
        }

        char responseBuffer[1024];
        int receivedBytes = ::recv(clientSocket, responseBuffer, sizeof(responseBuffer), 0);
        if (receivedBytes == SOCKET_ERROR)
        {
            if (WSAGetLastError() == WSAEWOULDBLOCK)
            {
                // 暂时无数据可读,等待下次检测
                continue;
            }
            socketsToRemove.push_back(clientSocket);
            continue;
        }
        else if (receivedBytes == 0)
        {
            // 客户端关闭连接
            socketsToRemove.push_back(clientSocket);
            continue;
        }
        responseBuffer[receivedBytes] = '\0';
        std::string responseData(responseBuffer);
        // 在这里可以根据客户端对心跳包的响应进行进一步判断和处理,比如验证响应内容是否正确等
        if (responseData != "HEARTBEAT_RESPONSE")
        {  // 假设正确响应内容为 HEARTBEAT_RESPONSE
            socketsToRemove.push_back(clientSocket);
            continue;
        }

        lastHeartbeatTime = currentTime;
    }

    // 移除已断开连接或异常的客户端(此处调用下面定义的 removeDisconnectedClients 函数,无参数传递)
    removeDisconnectedClients();
}

// 移除已断开连接的客户端(更新函数定义,无参数)
void TcpServer::removeDisconnectedClients() 
{
    std::vector<SOCKET> socketsToRemove;
    for (size_t i = 0; i < clientSockets.size(); ++i)
    {
        SOCKET clientSocket = clientSockets[i];
        // 检查是否已经判定为需要移除(比如在前面接收数据或心跳检测环节标记为要移除)
        if (clientLastHeartbeatTime.find(clientSocket) == clientLastHeartbeatTime.end()) 
        {
            socketsToRemove.push_back(clientSocket);
        }
    }

    for (SOCKET socketToRemove : socketsToRemove)
    {
        auto it = std::find(clientSockets.begin(), clientSockets.end(), socketToRemove);
        if (it != clientSockets.end()) {
            clientSockets.erase(it);
            clientLastHeartbeatTime.erase(socketToRemove);
        }
    }
}

// 处理服务器业务逻辑,通常在循环中调用
void TcpServer::handle() 
{
    acceptNewClients();
    receiveClientData();
    sendHeartbeatsAndCheck();
    removeDisconnectedClients();
}

main.cpp

#include "TcpServer.h"

int main() {
    TcpServer server;
    if (server.start(8080)) {
        while (true) {
            server.handle();
            // 可以在这里添加适当的延时,避免过于频繁地循环处理,消耗过多CPU资源
            Sleep(100);
        }
    }
    return 0;
}
Windows环境下C++多线程TCP通信 最近突然对传输层的东西有了兴趣...发现自己虽然学过计网也学过C++,却没有真正实现过客户端和服务器之间的通信,于是恶补了一下socket知识,再加上大佬们的指导,模仿着写了个demo... 直接上代码。 首先是服务器端,要注意如果一开始写了using namespace std; 那么就要注意std里面的bind和socket相关的bind是同名的...如果直接调用bind,实际上调用的是s 阅读详情

相关推荐

Windows 系统下搭建搭建网站教程(含内网穿透发布公网访问)

此教程中,我们将实现在Windows上搭建一个web站点,并通过cpolar内网穿透,将该站点免费发布上线,实现公网用户可正常访问本地web站点。关于cpolar,cpolar是一个非常强大的内网穿透工具,开发调试的必备利器。它可以将本地内网服务器的HTTP、HTTPS、TCP协议端口映射为公网地址端口,使得公网用户可以轻松访问您的内网服务器,无需部署至公网服务器。支持永久免费使用,无需公网IP,也无需设置路由器。

不会编程的攻城狮 2501

windows下编译WebRTC源码并运行官方demo

一、环境 win10操作系统,并装有vs2019、windows sdk、git等常规开发软件。最好装上python,我用的版本是2.7 二、下载源码并编译 打开windows cmd命令行。 //切换到webrtc的下载目录,自己新建的文件夹 cd C:\webrtc set WINDOWSSDKDIR=C:\Program Files (x86)\Windows Kits\10 set GYP_MSVS_OVERRIDE_PATH=C:\Program Files (x86)\Microsoft Vis

weixin_43327696的博客 1609

Windows Server 2016域环境搭建:从零部署Active Directory与DNS配置详解

在企业IT基础设施中,集中化的身份与访问管理是提升运维效率和安全性的核心。其原理是通过部署目录服务,构建一个逻辑上的安全边界,实现对用户、计算机和策略的统一管控。这项技术的核心价值在于简化管理复杂度、强化安全策略执行并降低长期运维成本,广泛应用于需要统一认证、软件分发和合规审计的中小型企业网络环境。Active Directory作为微软生态下的主流解决方案,其部署与DNS服务的集成配置是关键实践环节。本文将以Windows Server 2016为平台,系统阐述域控制器部署过程中的网络规划、服务安装验证及

weixin_34008784的博客 265

简单TCP服务器端和客户端(源代码)

http://andylin02.iteye.com/blog/460742 简单TCP服务器端和客户端(源代码) 博客分类:  一亩三分地 SocketWindows Cpp代码   //客户端:   Cpp代码   #include    #include    #include       usi

linuxheik的专栏 1268

Windows下C语言的Socket编程例子(TCP和UDP)

1 TCP      Server端 #include "stdafx.h" #include #include #pragma comment(lib,"ws2_32.lib") int main(int argc, char* argv[]) { //初始化WSA WORD sockVersion = MAKEWORD(2,2); WSADATA wsa

遇见--专栏 1050

全网最全的AItium Designer 16下载资源与安装步骤

Altium Designer 除了全面继承包括Protel 99SE、Protel DXP在内的先前一系列版本的功能和优点外,还增加了许多改进和很多高端功能。该平台拓宽了板级设计的传统界面,全面集成了FPGA设计功能和SOPC设计实现功能,从而允许工程设计人员能将系统设计中的FPGA与PCB设计及嵌入式设计集成在一起。...

WQ的博客 1万+

java socket框架_优秀的国产高性能TCP/UDP/HTTP开源网络通信框架——HP-Socket

介绍HP-Socket是国人开发的一套高性能的TCP/UDP/HTTP网络通信框架,包含了服务端、客户端以及Agent组件,可用于各种不同应用场景的通信系统,并且提供了C/C++、C#、Delphi、E、Java、Python等编程语言接口。 HP-Socket 对通信层完全封装,应用程序不必关注通信层的任何细节;HP-Socket 提供基于事件通知模型的 API 接口,能非常简单高效地整合到新旧...

weixin_39665762的博客 1489

详解Numpy中的transpose方法

最近在学Numpy碰到了关于数组转置和换轴的概念,尤其是对tanspose方法有些疑惑,尤其是多维,查了不少资料,终于搞懂了。 Numpy数组的轴(axis) 所谓的**轴(axis)**可以理解为数组的维度。 具体而言,二维数组就是有两个维度,如果从空间上看,它就是一个平面,由x轴和y轴构成,而与此相对应的,该二维数组就有两个轴,x轴对应0轴,y轴对应1轴。 同理,三维数组有三个维度,空间上...

BlankGrid的博客 936

socket 编程(五) windows tcp

socket

wjmasd的博客 836

FPGA调试利器:VIO与ILA在Vivado中的实战应用指南

本文详细介绍了Vivado中FPGA调试工具VIO与ILA的实战应用技巧。VIO作为虚拟输入/输出工具,可实时调整参数;ILA作为集成逻辑分析仪,能高效捕获内部信号。文章通过具体案例展示了如何配置ILA采样深度、触发条件,以及VIO的动态参数调整功能,帮助开发者提升上板调试效率,解决常见通信失败、数据不同步等问题。

weixin_42553471的博客 424

Cgroup对进程所占用的CPU与内存资源同时进行限制的测试

测试环境:Ubuntu。处理器数量:1CPU。内存大小:2048MB。 以下是测试程序mem_cpu_test.c的代码。 将mem_cpu_test.c编译为可以运行的程序mem_cpu_test。 运行程序,并用top命令查看mem_cpu_test所占用的系统资源情况,可以看到,mem_cpu_test使用了50%左右的内存资源,也就是1000MB左右,并占用了接近全部的CPU资源。 关闭以上的程序后,在Cgroup子系统memory和cpu下分别创建进程组test1和test2。 并设置tes

qq_44998067的博客 1153

windows C++ TCP客户端

1. 接收数据线程相关的成员变量 :用于存储接收数据线程的句柄,通过函数创建线程时获取,用于后续对线程的操作,比如等待线程结束、关闭线程句柄等。 :布尔类型变量,用于标记接收数据线程是否正在运行,在启动线程时设置为,当需要停止线程(比如断开连接或者程序结束时)设置为,线程函数内部会根据这个变量来判断是否继续循环接收数据。 2. 函数 在成功连接到服务器后,不仅将标记设置为,还会创建并启动接收数据线程。通过函数创建线程,传入函数作为线程执行的入口点,并将当前对象指针作为参数传递进去,以便在线程函数中能够访

doubleintfloat的博客 860

无人驾驶Autoware导读

认知有限,望大家多多包涵,有什么问题也希望能够与大家多交流,共同成长!本文先对无人驾驶Autoware介绍做个简单的介绍,具体内容后续再更,其他模块可以参考去我其他文章提示:以下是本篇文章正文内容。

qq_35635374的博客 2397

Windows平台C++实现最简单TCP通信教程

极简单版本,无难点

Blue噜噜噜的博客 226

基于Simulink的电机轴电压与轴电流抑制仿真

本文带你完成了电机轴电压与轴电流抑制的Simulink仿真,实现了:✅ 揭示了共模电压 → 寄生电容 → 轴电压 → 轴承电蚀的完整链路✅ 搭建了含寄生参数的高频电机等效模型共模电压最小化PWM(源头抑制)dv/dt滤波器(路径阻断)轴接地(终端泄放) ✅ 通过仿真验证了轴电压从68 V降至<3 V的显著效果 ✅ 为高可靠性电机系统提供低成本、高效益的轴承保护方案。

amy_mhd的博客 163

【ArcGIS微课1000例】0145:如何按照自定义形状裁剪数据框?

使用绘图 工具条上的新建圆工具 可创建一个椭圆,使其包含要在该数据框中显示的数据范围。. 在基础工具工具条上单击选择元素工具 ,然后选择圆形。. 在内容列表中右键单击要裁剪的数据框,然后单击属性。. 单击裁剪选项下拉菜单,然后选择裁剪至形状。. 单击数据框属性 对话框中的数据框选项卡。还可以更改裁剪形状轮廓的边框选项。打开软件,添加配套实验数据包中。修改椭圆的属性,使其透明。. 单击所选图形的轮廓。. 单击指定形状按钮。

智慧空间实验室 953

Windows TCP 通信测试_1

手动输入的client会把服务端的进程阻塞住,导致另一个client的消息也进不来,手动输入消息后,会暂时解除当前阻塞,问题不小,小白太难了,后面再搞。应用函数 socket、bind、connect、listen、accept、recv、send(win下的函数)等。(bug:目前手动输入过长字符会有发送异常的情况出现)1、为了一次打印client发送的消息,做了一点愚蠢的特殊处理。目前也没超时,不能很好的处理多个客户端的互相影响。2、没有做超时,socket没有消息会一直阻塞;

weixin_41885845的博客 718

Java SSH框架学习

Java SSH框架学习

私信可回答各种问题~ 1789

windows win32 c++/c services服务编写sample demo

windows的服务程序不是简单的写一个console控制台程序然后加入服务就能运行成功的,需要遵循一定的代码规范,程序需要与系统的 SCM 交互,否则就会刚执行就被系统停止 两个windows 服务程序的sample demo the-complete-service-sample–Microsoft 使用 C++ 编写的基础 Windows 服务 可以对照以上使用windows api编写,以...

老专家的博客 893

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

flutter-webrtc-server与flutter-webrtc-demo集成教程:移动端实时通信实践

想要在Flutter应用中实现实时音视频通信吗?**flutter-webrtc-server**是一个专为Flutter WebRTC设计的信令服务器,它简化了移动端实时通信的搭建过程。本文将为您提供完整的集成教程,帮助您快速搭建自己的实时通信系统。无论您是Flutter新手还是有一定经验的开发者,都能通过本指南轻松上手这个强大的WebRTC信令服务器解决方案。 ## 🚀 什么是flutte

gitblog_00173的博客 684

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Windows网络编程~TCP/IP~c/s简单demo (三)

TCP客户端服务器: UDP客户端服务器: server端代码 #include <stdio.h> #include <stdlib.h> #include <WinSock2.h> #pragma comment(lib,"Ws2_32.lib") //标记 BOOL g_nFlag = TRUE; int main(void) { //打开网络库 WORD wdVersion = MAKEWORD(1, 1); WSADATA wsaData;

yazjy1的博客 527

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

【C/C++】TCP Demo传Image Raw Data

环境 Windows VS2019 调试只做了3次互传,且图像信息为虚拟的vector数据,仅做了实现,无校验和鲁棒性提升 host -> server:传输原始图像Image,以及图像属性的结构体 server->host:传输图像的覆盖数组参考1 参考2Host端:TCPHost.h Host端:TCPHost.cpp Server端:TCPServer.h Server端:TCPServer.cpp 实现效果Host端log: 实现效果Server端效果:

winnizap的博客 308

windows server 2022 部署前后端项目

在中,点击后,进入。

qq_43085008的博客 272

FreeRTOS-Plus-TCP Fuzz

FreeRTOS由美国的Richard Barry于2003年发布。2018年,亚马逊收购了FreeRTOS并将其改名为AWS FreeRTOS。收购前FreeRTOS经历了9个版本,收购后更新到V10。基于生成的协议模糊测试工具Boofuzz框架主要可以分为三个部分:(1) 数据生成模块Data Generation。

m0_56808314的博客 730

Python多人游戏网络编程:用socket实现TCP位置同步Demo

网络编程是构建多人游戏联机功能的核心基础。在客户端-服务器模型下,服务器作为权威状态源,通过socket通信接收并广播玩家数据。TCP协议提供可靠的字节流传输,但也带来了粘包与拆包问题,需要应用层设计消息边界。Python凭借简洁的语法和丰富的标准库,成为快速原型验证的理想选择。基于select事件循环可实现单线程管理多客户端连接,降低资源开销。这种技术方案广泛应用于中小型游戏的位置同步、状态广播等场景。从一个Python小游戏的联机需求出发,通过一个基于TCP的多人位置同步Demo,涵盖协议设计、服务端骨

cuankuangzhong6373的博客 519

Configure Guest RDMA on Windows Server 2019

Configure Guest RDMA on Windows Server 2019

勇往直前! 770
上一篇: C++ windows HTTP 服务器demo
下一篇: windows TCP client demo
越甲八千
博客等级 码龄11年 2956粉丝 553原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值