C++ 简单的UDP客户端与服务端

时间:2022-10-12 22:16:25

.h

#pragma once
#ifndef __C_UDP_OBJECT_H__
#define __C_UDP_OBJECT_H__

#define OS_PLATFORM_WIN

#include <string>

#ifdef OS_PLATFORM_WIN

#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib")

#else

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
//#include <sys/un.h>  
//#include <netdb.h>

#endif // !OS_PLATFORM_WIN

class CUdpObject
{
protected:
    CUdpObject();
    virtual ~CUdpObject();

public:
    virtual void SetParameter(int nPort, const char* szAddress = nullptr);

public:
    virtual int SendTo(const char* szData, int nDataLength);
    virtual int ReceiveFrom(char* szBuffer, int nBufferSize);

public:
    virtual const std::string& ToString() = 0;

protected:
    virtual struct sockaddr_in& SocketAddress();

protected:
#ifdef OS_PLATFORM_WIN
    SOCKET m_sktUdpObject;
#else
    int m_sktUdpObject;
#endif // !OS_PLATFORM_WIN
    struct sockaddr_in m_sktUdpObjectAddress = { 0 };
    volatile int m_nLastSendTransferred = 0;
    volatile int m_nLastReceiveTransferred = 0;

private:
    int m_nPort = 0;
    char m_szAddress[32] = { 0 };

private:
    CUdpObject(const CUdpObject&);
    CUdpObject& operator=(const CUdpObject&);
};


class CUdpClient : public CUdpObject
{
public:
    CUdpClient() 
    { 
        m_strEndPoint = "C:" + std::to_string(m_sktUdpObject); 
        printf("ctor %s.\r\n", ToString().c_str());
    };
    virtual ~CUdpClient() 
    { 
        printf("dctor %s.\r\n", ToString().c_str()); 
    };

public:
    virtual bool IsConnect();

public:
    virtual const std::string& ToString() override;

private:
    std::string m_strEndPoint;

private:
    CUdpClient(const CUdpClient&);
    CUdpClient& operator=(const CUdpClient&);
};


//Single Client
class CUdpServer : public CUdpObject
{
public:
    CUdpServer() 
    { 
        m_strEndPoint = "S:" + std::to_string(m_sktUdpObject);
        printf("ctor %s.\r\n", ToString().c_str());
    };
    virtual ~CUdpServer() 
    { 
        printf("dctor %s.\r\n", ToString().c_str()); 
    };

public:
    void SetParameter(int nPort, const char* szAddress = nullptr) override;

public:
    struct sockaddr_in & SocketAddress() override;

public:
    virtual const std::string& ToString() override;

private:
    struct sockaddr_in m_sktAddressClient = { 0 };

private:
    std::string m_strEndPoint;

private:
    CUdpServer(const CUdpServer&);
    CUdpServer& operator=(const CUdpServer&);
};

#endif // !__C_UDP_OBJECT_H__

 

.cpp

#include "UdpObject.h"

#include <cstdio>
#include <cstdlib>
#include <cstring>


CUdpObject::CUdpObject()
{
#ifdef OS_PLATFORM_WIN
    WSADATA stData;
    WSAStartup(MAKEWORD(2, 2), &stData);
#else
#endif // !OS_PLATFORM_WIN

    m_sktUdpObject = socket(AF_INET, SOCK_DGRAM, 0/*IPPROTO_UDP, IPPROTO_UDPLITE*/);
}
CUdpObject::~CUdpObject()
{
#ifdef OS_PLATFORM_WIN
    closesocket(m_sktUdpObject);
    WSACleanup();
#else
    //shutdown(m_sktUdpObject, SHUT_RDWR);
    close(m_sktUdpObject);
#endif // !OS_PLATFORM_WIN
}

void CUdpObject::SetParameter(int nPort, const char* szAddress)
{
    m_nPort = nPort;

    m_sktUdpObjectAddress.sin_family = AF_INET;
    m_sktUdpObjectAddress.sin_port = htons(m_nPort);

    if (nullptr != szAddress)
    {
        std::strcpy(m_szAddress, szAddress);
        m_sktUdpObjectAddress.sin_addr.s_addr = inet_addr(m_szAddress);
    }
    else
    {
        m_sktUdpObjectAddress.sin_addr.s_addr = INADDR_ANY;
    }
}

struct sockaddr_in& CUdpObject::SocketAddress()
{
    return m_sktUdpObjectAddress;
}

int CUdpObject::SendTo(const char* szData, int nDataLength)
{
    struct sockaddr_in& sktAddress = SocketAddress();

#ifdef OS_PLATFORM_WIN
    int nSktAddressSize = sizeof(sktAddress);
#else
    socklen_t nSktAddressSize = sizeof(sktAddress);
#endif // !OS_PLATFORM_WIN

    m_nLastSendTransferred = sendto(m_sktUdpObject, szData, nDataLength, 0, (const struct sockaddr*)&sktAddress, sizeof(sktAddress));

    return m_nLastSendTransferred;
}

int CUdpObject::ReceiveFrom(char* szBuffer, int nBufferSize)
{
    struct sockaddr_in& sktAddress = SocketAddress();

#ifdef OS_PLATFORM_WIN
    int nSktAddressSize = sizeof(sktAddress);
#else
    socklen_t nSktAddressSize = sizeof(sktAddress);
#endif // !OS_PLATFORM_WIN

    m_nLastReceiveTransferred = recvfrom(m_sktUdpObject, szBuffer, nBufferSize, 0, (struct sockaddr*)&sktAddress, &nSktAddressSize);

    return m_nLastReceiveTransferred;
}



bool CUdpClient::IsConnect()
{
    return m_nLastSendTransferred >= 0 || m_nLastReceiveTransferred >= 0;
}

const std::string& CUdpClient::ToString()
{
    return m_strEndPoint;
}


void CUdpServer::SetParameter(int nPort, const char* szAddress)
{
    CUdpObject::SetParameter(nPort, nullptr);

    bind(m_sktUdpObject, (const struct sockaddr*)&m_sktUdpObjectAddress, sizeof(m_sktUdpObjectAddress));
}

struct sockaddr_in& CUdpServer::SocketAddress()
{
    return m_sktAddressClient;
}

const std::string& CUdpServer::ToString()
{
    return m_strEndPoint;
}

.test.cpp

 
#include <cstring>
#include <iostream>

#include "UdpObject.h"

using namespace std;
 


//int cudp_test()
int main()
{
    char szBuffer[128] = { 0 };

    CUdpServer server;
    server.SetParameter(60001);

    {
        CUdpClient client;
        client.SetParameter(60001, "192.168.1.76");


        std::strcpy(szBuffer, "abcedfe");
        std::cout << "Client Send: " << szBuffer << std::endl;
        client.SendTo(szBuffer, std::strlen(szBuffer));


        memset(szBuffer, 0, sizeof(szBuffer));
        server.ReceiveFrom(szBuffer, sizeof(szBuffer));
        std::cout << "Server Receive : " << szBuffer << std::endl;


        std::strcpy(szBuffer, "daaaaaaaaaaaaaaaaa");
        std::cout << "Server Send: " << szBuffer << std::endl;
        server.SendTo(szBuffer, std::strlen(szBuffer));


        memset(szBuffer, 0, sizeof(szBuffer));
        client.ReceiveFrom(szBuffer, sizeof(szBuffer));
        std::cout << "Client Receive : " << szBuffer << std::endl;

        std::cout << client.IsConnect() << std::endl;
    }

    {
        CUdpClient client;
        client.SetParameter(60001, "192.168.1.76");


        std::strcpy(szBuffer, "aassasaassasasasasaaas");
        std::cout << "Client Send: " << szBuffer << std::endl;
        client.SendTo(szBuffer, std::strlen(szBuffer));


        memset(szBuffer, 0, sizeof(szBuffer));
        server.ReceiveFrom(szBuffer, sizeof(szBuffer));
        std::cout << "Server Receive : " << szBuffer << std::endl;


        std::strcpy(szBuffer, "vdvdvdvdvdvdvdvdvdv");
        std::cout << "Server Send: " << szBuffer << std::endl;
        server.SendTo(szBuffer, std::strlen(szBuffer));


        memset(szBuffer, 0, sizeof(szBuffer));
        client.ReceiveFrom(szBuffer, sizeof(szBuffer));
        std::cout << "Client Receive : " << szBuffer << std::endl;

        std::cout << client.IsConnect() << std::endl;
    }
    
    std::cout << "Done." << std::endl;
    getchar();

    return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 2.8.5)
project(upd_test)

set(TARGET ${PROJECT_NAME})


set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/../../Release/)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
add_definitions(-DOS_PLATFORM_UNIX)

add_executable(${TARGET} UdpObject.cpp Test_UdpObject.cpp)
target_link_libraries(${TARGET})

 

.build.sh

#! /bin/sh

#
dirBuildShell="../Temp/"

#
if [ -d "${dirBuildShell}" ]; then
    rm -rf "${dirBuildShell}"
fi

#
if [ $# -ge 1 ]; then
    dirBuildShell="../$1/"
    rm -rf "${dirBuildShell}"
fi

#
if [ ! -d "${dirBuildShell}" ]; then
    mkdir "${dirBuildShell}"
    cd "${dirBuildShell}"
fi

#
cmake ../Test/ && make