liv 发表于 2019-3-14 10:45

LwUdpSocket Win32 api Udp Scoket的封装

LwUdpSocket类Win32 apiUdp Scoket的封装

众所周知, win32 api 有"神奇"之效, 只要将它们样拼积木一样堆在一起,就能实现很多很酷的东西, 但是它的数量太多, 仅微软文档开放出来足足有三千多个并且参数类型各种宏定义,使用时出了问题时常让我们摸不头脑, 查msdn也是很消耗时间, 所以要将这些 Win Api 分门别类 的封装起来, 以后方便使用. 当然做简单的封装就可以了,不需要样mfc或者是Qt那样

封装理论上成员都应该是私有的, 让类的外部无法直接访问到其成员, 需要通过开放接口访问 (当然用点手段还是能访问的),所以我将三个成员定义私有的
private:
    SOCKET _socket; // 本地套接字
    const char* _ip; // ip地址
    int _port; // 端口号

曾经我是这么定义SOCKET* _socket, 当初我以为它是个结构体, 在c++中如果将结构体直接赋值给另一个变量, 系统会将这个结构体的所占内存空间拷贝过去,
影响程序运行速度, 所以我将其定义成指针, 深究之下发现, 它居然只是个unsigned int, 只是整型就没必须定义成指针了, 只是4个字节而已
SOCKET 是 UINT_PTR的别名
而UINT_PTR是unsigned int的别名

之后按照正常创建udp socket 流程封装了几个方法, 网络环增初始化以及socket 创建都在构造函数中, 当然了socket的关闭以及各种清除都在析构函数中:
LwUdpSocket(const char *ip, unsigned int port);
        ~LwUdpSocket();
        SOCKET GetSocket(); // 获取socket句柄
        bool Bind(); // 绑定地址
        int Send(const char *ip, unsigned int port, const char *buffer, int len); // 发送信息, 如果成功, 则返回发送的字节数,失败则返回SOCKET_ERROR

        // 接收消息, 返回-1表示接收失败, 注意如果你的buff长度是512, 那么len就不能大于512
        // buff只能在堆中申请内存, 栈中申请这个封装的方法会失败
        int Recv(char* buffer, int len, sockaddr_in* sockaddr);

完整的代码
LwUdpSocket.h
#ifndef __LW_UDP_SOCKET_H__
#define __LW_UDP_SOCKET_H__

#include "LwNetworkInterface.h" // 需要这个类的方法辅助

// udp socket的封装
class LwUdpSocket
{
private:
        SOCKET _socket; // 本地套接字
        const char* _ip; // ip地址
        int _port; // 端口号
public:
        LwUdpSocket(const char *ip, unsigned int port);
        ~LwUdpSocket();
        SOCKET GetSocket(); // 获取socket句柄
        bool Bind(); // 绑定地址
        int Send(const char *ip, unsigned int port, const char *buffer, int len); // 发送信息, 如果成功, 则返回发送的字节数,失败则返回SOCKET_ERROR

        // 接收消息, 返回-1表示接收失败, 注意如果你的buff长度是512, 那么len就不能大于512
        // buff只能在堆中申请内存, 栈中申请这个封装的方法会失败
        int Recv(char* buffer, int len, sockaddr_in* sockaddr);
};

#endif // !__LW_UDP_SOCKET_H__

LwUdpSocket.cpp
#include "LwUdpSocket.h"

LwUdpSocket::LwUdpSocket(const char *ip, unsigned int port)
{
        // 初始化网络环境
        LwNetworkInterface::InitWinsock();

        this->_ip = ip;
        this->_port = port;
        this->_socket = NULL;
        this->_socket = socket(AF_INET, SOCK_DGRAM, 0);
}

LwUdpSocket::~LwUdpSocket()
{
        if (this->_socket != NULL)
        {
                closesocket(this->_socket);
        }

        // 清除网络环境
        LwNetworkInterface::ClearWinsock();
}

SOCKET LwUdpSocket::GetSocket()
{
        return this->_socket;
}


bool LwUdpSocket::Bind()
{
        sockaddr_in address = LwNetworkInterface::CreateSocketAddr(this->_ip, this->_port);
        return bind(this->_socket, (sockaddr *)&address, sizeof(address)) == 0;
}


int LwUdpSocket::Send(const char *ip, unsigned int port, const char *buffer, int len)
{
        sockaddr_in sendAddress = LwNetworkInterface::CreateSocketAddr(ip, port);
        return sendto(this->_socket, buffer, len, 0, (SOCKADDR *)&sendAddress, sizeof(sendAddress));
}


int LwUdpSocket::Recv(char* buffer, int len, sockaddr_in* socketAddress)
{
        int socketAddressLen = sizeof(*socketAddress);
        return recvfrom(this->_socket, buffer, len, 0, (SOCKADDR *)socketAddress, &socketAddressLen);
}

如有错误, 给予指出, 非常感谢!


页: [1]
查看完整版本: LwUdpSocket Win32 api Udp Scoket的封装