2025-11-11 17:46:19 +08:00
|
|
|
|
#ifndef CC_Socket_
|
|
|
|
|
|
#define CC_Socket_
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
|
|
#include "CC.h"
|
|
|
|
|
|
#include "CCString.h"
|
|
|
|
|
|
|
|
|
|
|
|
#define SockError -1
|
2025-12-03 18:08:23 +08:00
|
|
|
|
#define CC_Sock_Close 0
|
2025-11-11 17:46:19 +08:00
|
|
|
|
|
|
|
|
|
|
// 定义主机信息结构体
|
|
|
|
|
|
struct CCHostInfo
|
|
|
|
|
|
{
|
|
|
|
|
|
std::string IPAddress;
|
|
|
|
|
|
CCInt Port = -1;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 定义套接字选项枚举
|
|
|
|
|
|
enum CCOpt
|
|
|
|
|
|
{
|
|
|
|
|
|
BROADCAST,
|
2025-12-03 18:08:23 +08:00
|
|
|
|
REUSEADDR,
|
|
|
|
|
|
REUSEPORT,
|
|
|
|
|
|
NOBLOCK,
|
|
|
|
|
|
LINGER_t,
|
|
|
|
|
|
SNDBUF,
|
|
|
|
|
|
RCVBUF,
|
|
|
|
|
|
TIMESTAMP,
|
2025-11-11 17:46:19 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 定义地址类型枚举
|
|
|
|
|
|
enum CCAddress
|
|
|
|
|
|
{
|
|
|
|
|
|
Local,
|
|
|
|
|
|
Any
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
|
|
|
|
|
|
|
#define MSL_N 0
|
|
|
|
|
|
|
|
|
|
|
|
// Windows平台下WSA初始化与清理类
|
|
|
|
|
|
class WinWSADWAInitAndClean
|
|
|
|
|
|
{
|
|
|
|
|
|
public:
|
|
|
|
|
|
WSADATA wsd{};
|
|
|
|
|
|
WinWSADWAInitAndClean(){
|
|
|
|
|
|
if (WSAStartup(MAKEWORD(2, 2), &this->wsd) != 0){
|
|
|
|
|
|
WSACleanup();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
~WinWSADWAInitAndClean(){
|
|
|
|
|
|
WSACleanup();
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
static WinWSADWAInitAndClean winsc;
|
|
|
|
|
|
|
|
|
|
|
|
#elif __linux__
|
|
|
|
|
|
#define MSL_N MSG_NOSIGNAL
|
|
|
|
|
|
#define SOCKET_ERROR (-1)
|
|
|
|
|
|
#include <sys/socket.h>
|
|
|
|
|
|
#include <netinet/in.h>
|
|
|
|
|
|
#include <linux/if.h>
|
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
|
#include <ifaddrs.h>
|
|
|
|
|
|
#include <netdb.h>
|
|
|
|
|
|
#include <sys/select.h>
|
|
|
|
|
|
#include "poll.h"
|
|
|
|
|
|
typedef int SOCKET;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
// 命名空间CTL,包含网络编程相关类和枚举
|
|
|
|
|
|
namespace CTL {
|
|
|
|
|
|
enum IPVX
|
|
|
|
|
|
{
|
|
|
|
|
|
IPV4 = AF_INET,
|
|
|
|
|
|
IPV6 = AF_INET6
|
|
|
|
|
|
};
|
|
|
|
|
|
enum TORU
|
|
|
|
|
|
{
|
|
|
|
|
|
TCP = IPPROTO_TCP,
|
|
|
|
|
|
UDP = IPPROTO_UDP
|
|
|
|
|
|
};
|
|
|
|
|
|
enum TYPE
|
|
|
|
|
|
{
|
|
|
|
|
|
STREAM = SOCK_STREAM,
|
|
|
|
|
|
DGRAM = SOCK_DGRAM
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Socket类,封装了网络编程的常见操作
|
|
|
|
|
|
class Socket{
|
|
|
|
|
|
public:
|
|
|
|
|
|
SOCKET Socketbit = -1;
|
|
|
|
|
|
sockaddr_in client = {}, server = {};
|
|
|
|
|
|
sockaddr_in6 client_6 = {}, server_6 = {};
|
|
|
|
|
|
short IPVx = 0;
|
|
|
|
|
|
// 默认构造函数
|
|
|
|
|
|
Socket() = default;
|
|
|
|
|
|
// 构造函数,初始化Socket
|
|
|
|
|
|
Socket(SOCKET sock);
|
|
|
|
|
|
// 初始化Socket并设置属性
|
|
|
|
|
|
bool Init(IPVX IPV4orIPV6, TORU TCPorUDP, TYPE Type = TYPE::STREAM);
|
|
|
|
|
|
// 获取Socket句柄
|
2025-12-03 18:08:23 +08:00
|
|
|
|
SOCKET GetSOCKET() const;
|
2025-11-11 17:46:19 +08:00
|
|
|
|
// 设置Socket选项
|
2025-12-03 18:08:23 +08:00
|
|
|
|
bool SetSockOpt(CCOpt opt) const;
|
2025-11-11 17:46:19 +08:00
|
|
|
|
// 设置Socket为非阻塞模式
|
2025-12-03 18:08:23 +08:00
|
|
|
|
void SetSocketNonBlocking() const;
|
2025-11-11 17:46:19 +08:00
|
|
|
|
// 检查Socket是否有可用数据
|
2025-12-03 18:08:23 +08:00
|
|
|
|
bool isDataAvailable() const;
|
2025-11-11 17:46:19 +08:00
|
|
|
|
// 获取本地IP地址
|
|
|
|
|
|
static std::vector<CTL::String> GetLocalIP(IPVX ipvx = IPVX::IPV4,int Number = 1);
|
|
|
|
|
|
// 获取客户端主机信息
|
2025-12-03 18:08:23 +08:00
|
|
|
|
CCHostInfo GetClientHost() const;
|
2025-11-11 17:46:19 +08:00
|
|
|
|
// 获取本地主机信息
|
2025-12-03 18:08:23 +08:00
|
|
|
|
CCHostInfo GetLocalHost() const;
|
2025-11-11 17:46:19 +08:00
|
|
|
|
// 连接到远程主机
|
|
|
|
|
|
bool Connect(const char* IP, unsigned short Port);
|
|
|
|
|
|
// 绑定Socket到指定地址和端口
|
|
|
|
|
|
bool Bind(const char* IP,unsigned short Port);
|
|
|
|
|
|
// 监听连接请求
|
|
|
|
|
|
bool Listen(unsigned short UserNum = 10);
|
|
|
|
|
|
// 接受连接请求
|
2025-12-03 18:08:23 +08:00
|
|
|
|
Socket Accept() const;
|
2025-11-11 17:46:19 +08:00
|
|
|
|
// 发送数据
|
2025-12-03 18:08:23 +08:00
|
|
|
|
bool Send(const char* str) const;
|
2025-11-11 17:46:19 +08:00
|
|
|
|
// 发送数据,带标志
|
2025-12-03 18:08:23 +08:00
|
|
|
|
bool Send(const char *__buf, size_t __n, int __flags) const;
|
2025-11-11 17:46:19 +08:00
|
|
|
|
// 发送数据到指定地址和端口
|
2025-12-03 18:08:23 +08:00
|
|
|
|
bool SendData(const char * str,const int length,sockaddr_in addr_in) const;
|
2025-11-11 17:46:19 +08:00
|
|
|
|
// 发送指定长度的数据
|
2025-12-03 18:08:23 +08:00
|
|
|
|
bool SendByte(const char* str,int len) const;
|
|
|
|
|
|
// 发送指定长度的数据
|
|
|
|
|
|
bool SendByte(const char* str,int len,int* ret) const;
|
2025-11-11 17:46:19 +08:00
|
|
|
|
// UDP发送数据
|
2025-12-03 18:08:23 +08:00
|
|
|
|
bool UDPSend(const char* str,const char* IP,int Port) const;
|
2025-11-11 17:46:19 +08:00
|
|
|
|
// UDP发送指定长度的数据
|
2025-12-03 18:08:23 +08:00
|
|
|
|
bool UDPSendByte(const char* str, ByteHander len, const char* IP, int Port) const;
|
2025-11-11 17:46:19 +08:00
|
|
|
|
// UDP发送指定长度的数据
|
2025-12-03 18:08:23 +08:00
|
|
|
|
bool UDPSendByte(void* str, ByteHander len, const char* IP, int Port) const;
|
2025-11-11 17:46:19 +08:00
|
|
|
|
// 接收数据
|
2025-12-03 18:08:23 +08:00
|
|
|
|
ByteHander RecvData(char* buffer,ByteHander lens) const;
|
2025-11-11 17:46:19 +08:00
|
|
|
|
// UDP接收数据
|
2025-12-03 18:08:23 +08:00
|
|
|
|
ByteHander UDPRecvData(char* buffer,ByteHander lens,CCHostInfo* info) const;
|
2025-11-11 17:46:19 +08:00
|
|
|
|
// 关闭Socket
|
|
|
|
|
|
void Close();
|
|
|
|
|
|
// 获取数据头部
|
2025-12-03 18:08:23 +08:00
|
|
|
|
static bool GetDateHead(char* data, ByteHander* size);
|
2025-11-11 17:46:19 +08:00
|
|
|
|
// 获取字符串头部
|
2025-12-03 18:08:23 +08:00
|
|
|
|
static bool GetStrHead(char* data,ByteHander size);
|
2025-11-11 17:46:19 +08:00
|
|
|
|
// 重载等号运算符,比较Socket对象是否相等
|
2025-12-03 18:08:23 +08:00
|
|
|
|
bool operator == (Socket socket) const;
|
2025-11-11 17:46:19 +08:00
|
|
|
|
// 重载不等号运算符,比较Socket对象是否不等
|
2025-12-03 18:08:23 +08:00
|
|
|
|
bool operator != (Socket socket) const;
|
2025-11-11 17:46:19 +08:00
|
|
|
|
// 检查连接是否有效
|
2025-12-03 18:08:23 +08:00
|
|
|
|
bool isConnectionAlive() const;
|
2025-11-11 17:46:19 +08:00
|
|
|
|
// 检查Socket是否可写
|
|
|
|
|
|
static bool IsSocketWritable(SOCKET sock);
|
|
|
|
|
|
static int GetLastError();
|
|
|
|
|
|
private:
|
|
|
|
|
|
int sock = -1;
|
|
|
|
|
|
bool Stop = false;
|
|
|
|
|
|
int opt = 1;
|
|
|
|
|
|
};
|
|
|
|
|
|
class InetAddress {
|
|
|
|
|
|
std::string hostAddress;
|
|
|
|
|
|
std::string hostName;
|
|
|
|
|
|
IPVX Ip_x = IPVX::IPV4;
|
|
|
|
|
|
public:
|
|
|
|
|
|
// 默认构造函数
|
|
|
|
|
|
InetAddress() = default;
|
|
|
|
|
|
// 根据IP地址构造
|
|
|
|
|
|
explicit InetAddress(const std::string& ip) : hostAddress(ip) {}
|
|
|
|
|
|
explicit InetAddress(IPVX ip_x,const std::string& ip= "");
|
|
|
|
|
|
// 根据IP地址和主机名构造
|
|
|
|
|
|
InetAddress(const std::string& ip, const std::string& hostname)
|
|
|
|
|
|
: hostAddress(ip), hostName(hostname) {}
|
|
|
|
|
|
// 获取本地主机InetAddress对象
|
|
|
|
|
|
static InetAddress getLocalHost(IPVX ipvx = IPVX::IPV4);
|
|
|
|
|
|
// 根据主机名获取InetAddress对象
|
|
|
|
|
|
static std::vector<InetAddress> getAllByName(const std::string& host);
|
|
|
|
|
|
// 根据IP地址获取InetAddress对象
|
|
|
|
|
|
static InetAddress getByName(const std::string& host);
|
|
|
|
|
|
// 获取IP地址字符串
|
|
|
|
|
|
std::string getHostAddress() const;
|
|
|
|
|
|
// 获取主机名
|
|
|
|
|
|
std::string getHostName() const;
|
|
|
|
|
|
// 获取任意地址 (相当于Java中的InetAddress.getByName("0.0.0.0"))
|
|
|
|
|
|
static InetAddress getAnyAddress();
|
|
|
|
|
|
// 获取回环地址 (相当于Java中的InetAddress.getByName("localhost"))
|
|
|
|
|
|
static InetAddress getLoopbackAddress();
|
|
|
|
|
|
// 获取广播地址
|
|
|
|
|
|
static InetAddress getBroadcastAddress(IPVX ipvx = IPVX::IPV4);
|
|
|
|
|
|
// 重载相等运算符
|
|
|
|
|
|
bool operator==(const InetAddress& other) const;
|
|
|
|
|
|
// 重载不等运算符
|
|
|
|
|
|
bool operator!=(const InetAddress& other) const;
|
|
|
|
|
|
// 转换为字符串
|
|
|
|
|
|
std::string toString() const;
|
|
|
|
|
|
IPVX getIPx() const;
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|