Windows Practice_Socket 错误封装

来源:互联网 发布:linux查看ssh端口号 编辑:程序博客网 时间:2024/06/06 19:35

UDP简单通讯例子

需要注意的是:
inet_addr函数如果使用的是VS2014以上的库编译时,会报错,所以我们需要选择兼容XP的编译方式,具体设置在项目属性中设置。如图所示:
这里写图片描述

服务端

// SocketUDPServer.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <WinSock2.h>#include <Windows.h>#include <clocale>#pragma comment(lib, "ws2_32.lib")void PrintErrorMessage(DWORD dwErrorCode){    setlocale(LC_ALL, "chs");    wchar_t strErrorMessage[MAXBYTE] = { 0 };    FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, dwErrorCode, 0, strErrorMessage, MAXBYTE, nullptr);    wprintf(L"ErrorCode:%d    ErrorMessage:%s", dwErrorCode, strErrorMessage);}int main(){    WSAData wsaData;    int iErrorNumber = WSAStartup(MAKEWORD(2, 2), &wsaData);    if (iErrorNumber != 0)    {        printf("WSAStartup failed with error: %d\n", iErrorNumber);        return 1;    }    if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)    {        printf("Could not find a usable version of Winsock.dll\n");        WSACleanup();        return 1;    }    else    {        printf("The Winsock 2.2 dll was found okay\n");    }    SOCKET s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);    if (INVALID_SOCKET == s)    {        PrintErrorMessage(GetLastError());        WSACleanup();        return 1;    }    sockaddr_in sockaddrServer, socketaddrClient;    sockaddrServer.sin_family = AF_INET;    sockaddrServer.sin_port = htons(10086);    sockaddrServer.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");    bind(s, reinterpret_cast<sockaddr *>(&sockaddrServer), sizeof(sockaddrServer));    char buf[MAXBYTE] = { 0 };    int iLen = sizeof(sockaddr_in);    recvfrom(s, buf, MAXBYTE, 0, reinterpret_cast<sockaddr *>(&socketaddrClient), &iLen);    printf("received from Client:%s\r\n", buf);    scanf_s("%s", buf, MAXBYTE);    sendto(s, buf, MAXBYTE, 0, reinterpret_cast<sockaddr *>(&socketaddrClient), MAXBYTE);    closesocket(s);    WSACleanup();    system("pause");    return 0;}

客户端

// SocketUDPClient.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <WinSock2.h>#include <Windows.h>#include <clocale>#pragma comment(lib, "ws2_32.lib")void PrintErrorMessage(DWORD dwErrorCode){    setlocale(LC_ALL, "chs");    wchar_t strErrorMessage[MAXBYTE] = { 0 };    FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, dwErrorCode, 0, strErrorMessage, MAXBYTE, nullptr);    wprintf(L"ErrorCode:%d    ErrorMessage:%s", dwErrorCode, strErrorMessage);}int main(){    WSAData wsaData;    int iErrorNumber = WSAStartup(MAKEWORD(2, 2), &wsaData);    if (iErrorNumber != 0)    {        printf("WSAStartup failed with error: %d\n", iErrorNumber);        return 1;    }    if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)    {        printf("Could not find a usable version of Winsock.dll\n");        WSACleanup();        return 1;    }    else    {        printf("The Winsock 2.2 dll was found okay\n");    }    SOCKET s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);    if (INVALID_SOCKET == s)    {        PrintErrorMessage(GetLastError());        WSACleanup();        return 1;    }    sockaddr_in sockaddrClient;    sockaddrClient.sin_family = AF_INET;    sockaddrClient.sin_port = htons(10086);    sockaddrClient.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");    char buf[MAXBYTE] = "Hello";    int iResult = sendto(s, buf, MAXBYTE, 0, reinterpret_cast<sockaddr *>(&sockaddrClient), sizeof(sockaddr_in));    if (iResult == SOCKET_ERROR)    {        wprintf(L"sendto failed with error: %d\n", WSAGetLastError());        closesocket(s);        WSACleanup();        return 1;    }    recv(s, buf, MAXBYTE, 0);    printf("received from server:%s\r\n", buf);    closesocket(s);    WSACleanup();    system("pause");    return 0;}

Socket的错误封装

这个错误封装的唯一一个好处就是能够深入的了解一下TCP和UDP的区别。
这个类没有写完整,还差一点儿通讯的功能,实在是写不下去了,以后如果有时间想写的时候再写吧。
里面用到了一些异常处理的方法,其实这些异常是没有必要的,我们可以做一些错误处理就可以了,而没有必要都要抛个异常。
有兴趣的朋友可以将这个类完善一下,从而达到简单通讯的目的。

头文件

#ifndef _SOCKET_H_#define _SOCKET_H_#include <exception>#include <string>#include <WinSock2.h>#include <Windows.h>#include <vector>#pragma comment(lib, "ws2_32.lib")namespace PoEdu{    class SocketErrorException : public std::exception    {    public:        SocketErrorException(const char *msg, const int errorCode) : std::exception()        {            std::string temp = msg;            temp += std::to_string(errorCode);            len_ = temp.length() + sizeof(char);            CopyData(temp.c_str(), len_);        }        SocketErrorException(const SocketErrorException &other)        {            CopyData(other.msg_, other.len_);        }        SocketErrorException operator=(const SocketErrorException &other)        {            if (this == &other)            {                return *this;            }            CopyData(other.msg_, other.len_);            return *this;        }        ~SocketErrorException()        {            delete[] msg_;        }        virtual char const* what() const        {            return msg_;        }    private:        void CopyData(const char *data, const size_t len)        {            msg_ = new char[len_];            strcpy_s(msg_, len_, data);        }    private:        char *msg_;        size_t len_;    };    class Socket    {    public:        enum SocketType        {            SOCKETTYPE_UDP,            SOCKETTYPE_TCP        };        Socket(SocketType socketTyp) throw(SocketErrorException);        ~Socket() throw();        bool ServerStart(unsigned int port, unsigned maxCount);        bool ServerStart(sockaddr_in &addr, unsigned maxCount) throw(SocketErrorException);        bool ServerAccept();        bool Connect(const char *ip, unsigned int port);        bool Connect(sockaddr_in &addr);        bool Send(const char *data, const size_t len);        bool SendTo(const char *data, const size_t len, sockaddr_in &addr);        int Recv(char *data, const size_t maxSize);        int RecvFrom(char *data, const size_t maxSize, sockaddr_in &addr);    private:        SOCKET socket_;        SocketType socketType_;        bool server_;        std::vector<SOCKET> vecAcceptSockt_;    };}#endif//_SOCKET_H_

cpp文件

#include "stdafx.h"#include "Socket.h"#include <algorithm>namespace PoEdu{    Socket::Socket(SocketType socketTyp) : socketType_(socketTyp), server_(false)    {        WSAData wsaData;        int iErrorCode = WSAStartup(MAKEWORD(2, 2), &wsaData);        if (iErrorCode != 0)        {            throw SocketErrorException("WSAStartup failed with errorCode:", iErrorCode);        }        if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)        {            WSACleanup();            throw SocketErrorException("Could not find a usable version of Winsock.dll. ErrorCode:", wsaData.wVersion);        }        int socket_af = AF_INET, sock_type = SOCK_DGRAM, sock_protocal = IPPROTO_UDP;        if (socketType_ == SOCKETTYPE_TCP)        {            sock_type = SOCK_STREAM;            sock_protocal = IPPROTO_TCP;        }        socket_ = socket(socket_af, sock_type, sock_protocal);        if (socket_ == INVALID_SOCKET)        {            WSACleanup();            throw SocketErrorException("cocket error:", WSAGetLastError());        }    }    Socket::~Socket()    {        closesocket(socket_);        WSACleanup();    }    bool Socket::ServerStart(unsigned int port, unsigned maxCount)    {        sockaddr_in addr;        addr.sin_family = AF_INET;        addr.sin_port = htons(port);        addr.sin_addr.S_un.S_addr = INADDR_ANY;        // 127.0.0.1 环路地址        // 192.168.1.1 LAN网地址        // 110.110.11.1 上一级网络地址        return ServerStart(addr, maxCount);    }    bool Socket::ServerStart(sockaddr_in& addr, unsigned maxCount)    {        bool bRet = false;        do        {            if (::bind(socket_, (sockaddr *)&addr, sizeof(sockaddr_in)) == SOCKET_ERROR)            {                break;            }            if (socketType_ == SOCKETTYPE_TCP)            {                if (::listen(socket_, maxCount) == SOCKET_ERROR)                {                    break;                }            }            server_ = true;            bRet = true;        } while (false);        return bRet;    }    bool Socket::ServerAccept()    {        bool bRet = false;        if (server_ && socketType_ == SOCKETTYPE_TCP)        {            SOCKET s = ::accept(socket_, nullptr, nullptr);            if (s != SOCKET_ERROR)            {                vecAcceptSockt_.push_back(s);                bRet = true;            }        }        return bRet;    }    bool Socket::Connect(const char* ip, unsigned int port)    {        sockaddr_in addr;        addr.sin_family = AF_INET;        addr.sin_port = htons(port);        addr.sin_addr.S_un.S_addr = inet_addr(ip);        return Connect(addr);    }    bool Socket::Connect(sockaddr_in& addr)    {        bool bRet = false;        if (socketType_ == SOCKETTYPE_TCP)        {            if (::connect(socket_, (sockaddr *)&addr, sizeof(sockaddr_in)) != SOCKET_ERROR)            {                bRet = true;            }        }        return bRet;    }    bool Socket::Send(const char* data, const size_t len)    {        bool bRet = false;        if (socketType_ == SOCKETTYPE_TCP)        {            if (server_)            {                // 有可能群聊,也有可能单聊                // 假设群发                std::vector<int> vecRet;                for (auto value : vecAcceptSockt_)                {                    vecRet.push_back(::send(value, data, len, 0));                }                if (std::find_if(vecRet.begin(), vecRet.end(), [](int result)                {                    return result == SOCKET_ERROR;                }) == vecRet.end())                {                    bRet = true;                }            }            else            {                if (::send(socket_, data, len, 0) != SOCKET_ERROR)                {                    bRet = true;                }            }        }        return bRet;    }    bool Socket::SendTo(const char* data, const size_t len, sockaddr_in &addr)    {        bool bRet = true;        ::sendto(socket_, data, len, 0, (sockaddr *)&addr, sizeof(addr));        return bRet;    }    int Socket::Recv(char* data, const size_t maxSize)    {        if (socketType_ == SOCKETTYPE_TCP)        {            if (server_)            {                int iRet = 0;                for (auto value : vecAcceptSockt_)                {                    // 用多线程,每个线程对应一个客户端                    iRet += ::recv(value, data, maxSize, 0);                }                return iRet;            }            else            {                return ::recv(socket_, data, maxSize, 0);            }        }    }    int Socket::RecvFrom(char* data, const size_t maxSize, sockaddr_in& addr)    {        return 0;    }}// server -> client 一呼一应
原创粉丝点击