socket.h 5.72 KB
Newer Older
lishen's avatar
lishen committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
117
118
119
120
#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 {
namespace host {

#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);

} // namespace host
} // namespace net
} // namespace hardware
} // namespace sccl