C++之基于Winsock2封装UDPServer与UDPClient

news/2024/5/18 13:38:49 标签: c++, winsock, udp, server, client

文章目录

    • Socket过程
    • UDPServer.h
    • UDPServer.cpp
    • UDPClient.h
    • UDPClient.cpp
    • main.cpp
    • CMakeLists.txt
    • 测试截图

Socket过程

  • UDPServer

  • UDPClient

UDPServer.h

#ifndef UDPSERVER_H_INCLUDED
#define UDPSERVER_H_INCLUDED

#include <iostream>
#include <string>
#include <Winsock2.h>

class UDPServer
{
private:
    WORD sockVersion;
    WSADATA wsaData;
    SOCKET udpSocket;
    sockaddr_in localAddr;
    sockaddr_in remoteAddr; // Client
    const int MSG_SIZE = 1024;

public:
    UDPServer();
    ~UDPServer();
    void Bind(u_short port);
    void Receive();
    bool Send(std::string message);
};

#endif // UDPSERVER_H_INCLUDED

UDPServer.cpp

#include "UDPServer.h"

UDPServer::UDPServer()
{
    sockVersion = MAKEWORD(2, 2);
    WSAStartup(sockVersion, &wsaData);
    udpSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
}

UDPServer::~UDPServer()
{
    closesocket(udpSocket);
    WSACleanup();
}

void UDPServer::Bind(u_short port)
{
    localAddr.sin_family = AF_INET;
    localAddr.sin_port = htons(port);
    // localAddr.sin_addr.S_un.S_addr = INADDR_ANY; // 0.0.0.0
    localAddr.sin_addr.S_un.S_addr = inet_addr("0.0.0.0");
    bind(udpSocket, (const sockaddr *)&localAddr, sizeof(localAddr));
}

void UDPServer::Receive()
{
    while (true)
    {
        char recvBuffer[MSG_SIZE];
        int localAddrSize = sizeof(localAddr);
        int lenRemoteAddr = sizeof(remoteAddr);
        int len = recvfrom(udpSocket, recvBuffer, MSG_SIZE, 0, (SOCKADDR *)&remoteAddr, &lenRemoteAddr);
        if (len > 0)
        {
            recvBuffer[len] = '\0';
            std::cout << "[" << inet_ntoa(remoteAddr.sin_addr) << ":" << remoteAddr.sin_port << "] -> " << recvBuffer << std::endl;
        }
    }
}

bool UDPServer::Send(std::string message)
{
    int ret = sendto(udpSocket, message.c_str(), message.length(), 0, (sockaddr *)&remoteAddr, sizeof(remoteAddr));
    if (ret == SOCKET_ERROR)
    {
        return false;
    }
    else
    {
        return true;
    }
}

UDPClient.h

#ifndef UDPCLIENT_H_INCLUDED
#define UDPCLIENT_H_INCLUDED

#include <iostream>
#include <string>
#include <Winsock2.h>

class UDPClient
{
private:
    WORD sockVersion;
    WSADATA wsaData;
    SOCKET udpSocket;
    sockaddr_in localAddr;
    sockaddr_in remoteAddr; // Client
    const int MSG_SIZE = 1024;

public:
    UDPClient();
    ~UDPClient();
    void Bind(std::string ip, u_short port);
    void Receive();
    bool Send(std::string message);
};

#endif // UDPCLIENT_H_INCLUDED

UDPClient.cpp

#include "UDPClient.h"

UDPClient::UDPClient()
{
    sockVersion = MAKEWORD(2, 2);
    WSAStartup(sockVersion, &wsaData);
    udpSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
}

UDPClient::~UDPClient()
{
    closesocket(udpSocket);
    WSACleanup();
}

void UDPClient::Bind(std::string ip, u_short port)
{
    localAddr.sin_family = AF_INET;
    localAddr.sin_port = htons(port);
    localAddr.sin_addr.S_un.S_addr = INADDR_ANY; // 0.0.0.0
    remoteAddr = localAddr;
    remoteAddr.sin_addr.S_un.S_addr = inet_addr(ip.c_str());
    bind(udpSocket, (const sockaddr *)&localAddr, sizeof(localAddr));
    Send("Hello");
}

void UDPClient::Receive()
{
    while (true)
    {
        char recvBuffer[MSG_SIZE];
        int localAddrSize = sizeof(localAddr);
        int lenRemoteAddr = sizeof(remoteAddr);
        int len = recvfrom(udpSocket, recvBuffer, MSG_SIZE, 0, (SOCKADDR *)&remoteAddr, &lenRemoteAddr);
        if (len > 0)
        {
            recvBuffer[len] = '\0';
            std::cout << "[" << inet_ntoa(remoteAddr.sin_addr) << ":" << remoteAddr.sin_port << "] -> " << recvBuffer << std::endl;
        }
    }
}

bool UDPClient::Send(std::string message)
{
    int ret = sendto(udpSocket, message.c_str(), message.length(), 0, (sockaddr *)&remoteAddr, sizeof(remoteAddr));
    if (ret == SOCKET_ERROR)
    {
        return false;
    }
    else
    {
        return true;
    }
}

main.cpp

#include <iostream>
#include <thread>
#include <string>

#include "UDPClient.h"
#include "UDPServer.h"

int main()
{
    std::cout << "[0] -> UDPServer"
              << "\n"
              << "[1] -> UDPClient" << std::endl;
    u_int flag = 2;
    std::cin >> flag;

    switch (flag)
    {
    case 0:
    {
        std::cout << "[UDPServer] -> Start" << std::endl;
        UDPServer udpServer;
        udpServer.Bind(6789);
        std::thread recvThread(&UDPServer::Receive, &udpServer);

        // 主线程
        while (true)
        {
            std::cout << "\n[Input] -> ";
            std::string msg;
            std::cin >> msg;
            if (udpServer.Send(msg))
            {
                std::cout << "[UDPServer] -> " << msg << std::endl;
            }
            else
            {
                std::cout << "[ErrorCode] -> " << GetLastError() << std::endl;
            }
        }

        // 等待线程结束
        recvThread.join();

        std::cout << "[UDPServer] -> Stop" << std::endl;
        break;
    }
    case 1:
    {
        std::cout << "[UDPClient] -> Start" << std::endl;
        UDPClient udpClient;
        udpClient.Bind("127.0.0.1", 6789);
        std::thread recvThread(&UDPClient::Receive, &udpClient);

        // 主线程
        while (true)
        {
            std::cout << "\n[Input] -> ";
            std::string msg;
            std::cin >> msg;
            if (udpClient.Send(msg))
            {
                std::cout << "[UDPClient] -> " << msg << std::endl;
            }
            else
            {
                std::cout << "[ErrorCode] -> " << GetLastError() << std::endl;
            }
        }

        // 等待线程结束
        recvThread.join();

        std::cout << "[UDPClient] -> Stop" << std::endl;
        break;
    }

    default:
        break;
    }

    system("pause");
    return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.0.0)
project(UDPProtocol VERSION 0.1.0 LANGUAGES CXX)

add_executable(${PROJECT_NAME} 
    UDPClient.cpp
    UDPServer.cpp
    main.cpp)

if(WIN32)
    target_link_libraries(${PROJECT_NAME} PRIVATE ws2_32)
endif()

测试截图


http://www.niftyadmin.cn/n/5097885.html

相关文章

Kotlin 协程再探之为什么使用协程反而更慢了?

前言 在几个月前&#xff0c;我曾经写了一篇文章&#xff0c;Kotlin 协程中的并发问题&#xff1a;我明明用 mutex 上锁了&#xff0c;为什么没有用&#xff1f;&#xff0c;讲述在某次 debug 某个问题时&#xff0c;发现同事写的 Koltin 协程某个不恰当的地方&#xff0c;并最…

RabbitMQ和spring boot整合及其他内容

在现代分布式应用程序的设计中&#xff0c;消息队列系统是不可或缺的一部分&#xff0c;它为我们提供了解耦组件、实现异步通信和确保高性能的手段。RabbitMQ&#xff0c;作为一款强大的消息代理&#xff0c;能够协助我们实现这些目标。在本篇CSDN博客中&#xff0c;我们将探讨…

2023年下半年软考考前注意事项!一定要看!

2023年下半年软考将于11月4-5日开考&#xff0c;由于首次实行机考&#xff0c;开考批次划分各地可能不同&#xff0c;所以具体考试时间请以准考证为准&#xff0c;请考生尽早打印准考证&#xff0c;了解考试时间、地点、考场规则等具体要求。 1、准考证打印时间 虽然大部分地区…

双目视觉实战--相机几何

目录 一、针孔摄像机和透镜 1. 针孔摄像机的原理 2. 近轴折射模型 3. 镜头畸变问题 二、摄像机几何 1. 数学基础 2. 相机坐标系&#xff08;空间点&#xff09;→像素坐标系的映射关系&#xff1a; 3. 规范化投影变换 4. 投影变换的性质 三、其他摄像机模型 1. 弱透视…

【C++ 中的友元函数:解密其神秘面纱】

友元函数&#xff0c;作为C中一个重要但常常被误解的概念&#xff0c;经常让初学者感到困惑。本文将带您逐步了解友元函数的含义、用途以及如何正确使用它们。 什么是友元函数&#xff1f; 在C中&#xff0c;友元函数是一种特殊的函数&#xff0c;它允许某个类或类的成员函数…

网工内推 | 南天软件,base北京,需持有CCIE认证,最高25k

01 北京南天软件有限公司 招聘岗位&#xff1a;IPT运维工程师 职责描述&#xff1a; 负责客户Cisco语音网络IPT ,CUCM的日常运维&#xff0c;扩容和项目支持&#xff0c;支持路由交换&#xff0c;无线等项目&#xff0c;实施工作以及相关实施文档。 任职要求&#xff1a; 1、…

MatrixOne Logtail 设计解析

Logtail 是 CN&#xff08;Computation Node&#xff09;与 TN&#xff08;Transaction Node&#xff09;之间的一种日志同步协议&#xff0c;是 CN 和 TN 协同工作的基础。本文将介绍 logtail 协议的基本定位&#xff0c;协议内容和产生过程&#xff0c;也会提及一些遇到的挑战…

【算法 | 模拟No.2】leetcode495. 提莫攻击

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【Leetcode】 &#x1f354;本专栏旨在提高自己算法能力的同时&#xff0c;记录一下自己的学习过程&#xff0c;希望…