socket.h 5.74 KB
Newer Older
lishen's avatar
lishen committed
1
2
3
4
5
6
7
8
9
10
11
12
13
#pragma once

#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/tcp.h>
#include <netdb.h>
#include <fcntl.h>
#include <poll.h>
#include "base.h"

namespace sccl {
namespace hardware {
namespace net {
14
namespace net_socket {
lishen's avatar
lishen committed
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116

#define MAX_IFS 16                                   // 最大接口数量
#define MAX_IF_NAME_SIZE 16                          // 每个接口名称的最大长度
#define SLEEP_INT 1000                               // 连接重试的休眠间隔,单位为微秒
#define RETRY_REFUSED_TIMES 2e4                      // 在报告超时之前,连接被拒绝的重试次数(总计20秒)
#define RETRY_TIMEDOUT_TIMES 3                       // 连接超时的重试次数(每次重试可能需要20秒)
#define SOCKET_NAME_MAXLEN (NI_MAXHOST + NI_MAXSERV) // 套接字名称的最大长度,包括主机名和服务名
#define SCCL_SOCKET_MAGIC 0x564ab9f2fc4b9d6cULL      // 用于标识套接字的魔数

/* 用于存储IPv4/IPv6通用套接字地址的联合体 */
union scclSocketAddress {     // 联合体用于存储不同类型的套接字地址
    struct sockaddr sa;       // 通用套接字地址
    struct sockaddr_in sin;   // IPv4套接字地址
    struct sockaddr_in6 sin6; // IPv6套接字地址
};

enum scclSocketState : uint8_t {
    scclSocketStateNone           = 0, // 未定义状态
    scclSocketStateInitialized    = 1, // 已初始化状态
    scclSocketStateAccepting      = 2, // 正在接受连接状态
    scclSocketStateAccepted       = 3, // 已接受连接状态
    scclSocketStateConnecting     = 4, // 正在连接状态
    scclSocketStateConnectPolling = 5, // 连接轮询状态
    scclSocketStateConnected      = 6, // 已连接状态
    scclSocketStateReady          = 7, // 准备就绪状态
    scclSocketStateClosed         = 8, // 已关闭状态
    scclSocketStateError          = 9, // 错误状态
    scclSocketStateNum            = 10 // 状态总数
};

enum scclSocketType : uint8_t {
    scclSocketTypeUnknown   = 0, // 未知类型
    scclSocketTypeBootstrap = 1, // 启动类型
    scclSocketTypeProxy     = 2, // 代理类型
    scclSocketTypeNetSocket = 3, // 网络套接字类型
    scclSocketTypeNetIb     = 4  // 网络Infiniband类型
};

struct scclSocket {
    int fd;                       // 文件描述符
    int acceptFd;                 // 接受连接的文件描述符
    int timedOutRetries;          // 超时重试次数
    int refusedRetries;           // 被拒绝重试次数
    union scclSocketAddress addr; // 套接字地址
    volatile uint32_t* abortFlag; // 中止标志
    int asyncFlag;                // 异步标志
    enum scclSocketState state;   // 套接字状态
    int salen;                    // 地址长度
    uint64_t magic;               // 魔术数
    enum scclSocketType type;     // 套接字类型
};

#define SCCL_SOCKET_SEND 0
#define SCCL_SOCKET_RECV 1

//////////////////////////////////// socket工具 ////////////////////////////////////
// 将地址转换为字符串
const char* scclSocketToString(const union scclSocketAddress* addr, char* buf, const int numericHostForm = 1);
// 从字符串中获取地址
scclResult_t scclSocketGetAddrFromString(union scclSocketAddress* ua, const char* ip_port_pair);
// 查找与子网匹配的接口
int scclFindInterfaceMatchSubnet(char* ifNames, union scclSocketAddress* localAddrs, union scclSocketAddress* remoteAddr, int ifNameMaxSize, int maxIfs);
// 查找可用的socket网络接口
int scclFindSocketInterfaces(char* ifNames, union scclSocketAddress* ifAddrs, int ifNameMaxSize, int maxIfs);

//////////////////////////////////// socket基础操作 ////////////////////////////////////
// 进行socket操作
scclResult_t scclSocketProgress(int op, struct scclSocket* sock, void* ptr, int size, int* offset);
// 等待socket操作完成
scclResult_t scclSocketWait(int op, struct scclSocket* sock, void* ptr, int size, int* offset);
// 发送数据
scclResult_t scclSocketSend(struct scclSocket* sock, void* ptr, int size);
// 接收数据
scclResult_t scclSocketRecv(struct scclSocket* sock, void* ptr, int size);
// 尝试接收数据
scclResult_t scclSocketTryRecv(struct scclSocket* sock, void* ptr, int size, int* closed, bool blocking);
// 关闭socket
scclResult_t scclSocketClose(struct scclSocket* sock);

//////////////////////////////////// 应用socket ////////////////////////////////////
// 初始化一个socket
scclResult_t scclSocketInit(struct scclSocket* sock,
                            union scclSocketAddress* addr = NULL,
                            uint64_t magic                = SCCL_SOCKET_MAGIC,
                            enum scclSocketType type      = scclSocketTypeUnknown,
                            volatile uint32_t* abortFlag  = NULL,
                            int asyncFlag                 = 0);
// 创建一个监听socket。sock->addr可以预先填充IP和端口信息。成功调用后设置sock->fd
scclResult_t scclSocketListen(struct scclSocket* sock);
// 获取socket地址
scclResult_t scclSocketGetAddr(struct scclSocket* sock, union scclSocketAddress* addr);
// 连接到sock->addr。成功调用后设置sock->fd。
scclResult_t scclSocketConnect(struct scclSocket* sock, int portReuse = 0);
// 返回socket连接状态。
scclResult_t scclSocketReady(struct scclSocket* sock, int* running);
// 接受来自listenSock->fd的传入连接,并在sock->fd中保持文件描述符,远程端IP/端口在sock->addr中。
scclResult_t scclSocketAccept(struct scclSocket* sock, struct scclSocket* ulistenSock);
// 获取socket文件描述符
scclResult_t scclSocketGetFd(struct scclSocket* sock, int* fd);
// 设置socket文件描述符
scclResult_t scclSocketSetFd(int fd, struct scclSocket* sock);

117
} // namespace net_socket
lishen's avatar
lishen committed
118
119
120
} // namespace net
} // namespace hardware
} // namespace sccl