MyWebServer开发日记-socket

打算把 tinyWebServer 重写成跨平台(Windows and Linux)的。

这里首先需要跨平台的 sokcet,主要参考 尹圣雨 的 TCP/IP 网络编程 来着:

代码写的有些笨,欢迎批评:

首先是一个 socket 类,主要封装了 常用操作,通过宏定义分别针对 Linux 和 Windows 处理 :

#ifndef _SOCKET_H_
#define _SOCKET_H_

#ifdef _WIN32
#include 
#else
#include 
#include 
#include 
#include 
#include 
#endif

#include 
#include 
#include 

#include 
#include 
#include 
#include 
#include 


#ifdef _WIN32
    using socklen_t = int;
#else
    using SOCKET = int; //文件描述符
    static constexpr int INVALID_SOCKET  = -1; 
    static constexpr int SOCKET_ERROR = -1;
#endif

class Socket {

public:
    Socket():Socket(PF_INET,SOCK_STREAM,IPPROTO_TCP){}
    Socket(int domain, int type, int protocal);
    Socket(SOCKET socket): m_socket(socket){}

    ~Socket() noexcept;

    void bind(sockaddr *addr, socklen_t addrlen);

    void listen(int queueLen= 5);

    Socket accept(sockaddr *addr, socklen_t *addrlen);

    void connect(sockaddr *addr, socklen_t len);

    SOCKET getSocket() { return m_socket; }

private:
    SOCKET m_socket;
};



class WinSockMgr {
public:
    static WinSockMgr *getInstance() 
    {
        static WinSockMgr instance;
        return &instance;
    }
private:
    WinSockMgr();
    ~WinSockMgr() noexcept;
};

#endif

这里 WinSockMgr 主要用来管理 WinSock 的一些启动销毁工作。

然后是实现,这里直接报错就抛异常:

#include "socket.h"

namespace {
#ifdef _WIN32
    WinSockMgr* winSockMgr = WinSockMgr::getInstance();
#endif
}

std::string getErrorStr(const char *str) 
{
    std::ostringstream errStr;
    errStr << str << " with errno [" << errno << "]";
    return errStr.str();
}


Socket::Socket(int domain, int type, int protocal) try //这里的 try 纯属多此一举
{
    m_socket = socket(domain,type,protocal);
    if (INVALID_SOCKET == m_socket) {
        std::string errStr = getErrorStr("socket() failed!");
        std::cerr << errStr << std::endl;
        throw std::runtime_error(errStr);
    }
} catch(const std::runtime_error& e) {
    throw;
}

Socket::~Socket()
{
#ifdef _WIN32
    if (0 != closesocket(m_socket)) {
        std::cerr << "closesocket() failed!" << std::endl;
    }
#else
    close(m_socket);
#endif
}

void Socket::bind(sockaddr *addr,socklen_t len)
{
    if (0 != ::bind(m_socket,addr,len)) {
        std::string errStr = getErrorStr("bind() failed!");
        std::cerr << errStr << std::endl;
        throw std::runtime_error(errStr);
    }
}

// queueLen = 5
void Socket::listen(int queueLen)
{
    // 第二个参数是 请求等待的数量
    if (0 != ::listen(m_socket,queueLen)) {
        std::string errStr = getErrorStr("listen() failed!");
        std::cerr << errStr << std::endl;
        throw std::runtime_error(errStr);
    }
}

Socket Socket::accept(sockaddr *addr, socklen_t *addrlen)
{
    SOCKET socket = ::accept(m_socket,addr,addrlen);
    if (INVALID_SOCKET == socket) {
        std::string errStr = getErrorStr("accept() failed!");
        std::cerr << errStr << std::endl;
        throw std::runtime_error(errStr);
    }
    return Socket{socket};
}

void Socket::connect(sockaddr *addr, socklen_t addrlen)
{
    if (SOCKET_ERROR == ::connect(m_socket,addr,addrlen)) {
        std::string errStr = getErrorStr("connect() failed!");
        std::cerr << errStr << std::endl;
        throw std::runtime_error(errStr);
    }
}



WinSockMgr::WinSockMgr() {
#ifdef _WIN32
    WSADATA wsaData;
    int ret = WSAStartup(MAKEWORD(2,2),&wsaData);
    if (ret != 0) {
        std::string errStr = getErrorStr("WSAStartup() failed!");
        std::cerr << errStr << "with return: [" << ret << "]" << std::endl;
        throw std::runtime_error(errStr);
    }
#endif
}

WinSockMgr::~WinSockMgr() {
#ifdef _WIN32
    if (0 != WSACleanup()) {
        std::string errStr = getErrorStr("WSACleanup() failed!");
        std::cerr << errStr << std::endl;
    }
#endif
}

代码写的不够简洁,还需要修改,但是先这样吧。

主要是简单的封装,也没啥好讲的。

你可能感兴趣的:(c++,笔记,学习)