372 lines
9.9 KiB
C
372 lines
9.9 KiB
C
#ifndef _SSOCKET_H_
|
||
#define _SSOCKET_H_
|
||
|
||
#include <stdio.h>
|
||
#include <string.h>
|
||
|
||
#define SSOCKET_VERSION_MAJOR 1
|
||
#define SSOCKET_VERSION_MINOR 0
|
||
#define SSOCKET_VERSION_PATCH 2
|
||
|
||
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
|
||
#define _OS_WIN 1
|
||
//define something for Windows (32-bit and 64-bit, this part is common)
|
||
#ifdef _WIN64
|
||
#define _OS_WIN64 1
|
||
//define something for Windows (64-bit only)
|
||
#else
|
||
#define _OS_WIN32 1
|
||
//define something for Windows (32-bit only)
|
||
#endif
|
||
#elif __APPLE__
|
||
#define _OS_APPLE 1
|
||
#include <TargetConditionals.h>
|
||
#if TARGET_IPHONE_SIMULATOR
|
||
#define _OS_APPLE_SIM 1
|
||
// iOS, tvOS, or watchOS Simulator
|
||
#elif TARGET_OS_MACCATALYST
|
||
#define _OS_APPLE_CATA 1
|
||
// Mac's Catalyst (ports iOS API into Mac, like UIKit).
|
||
#elif TARGET_OS_IPHONE
|
||
#define _OS_APPLE_PHO 1
|
||
// iOS, tvOS, or watchOS device
|
||
#elif TARGET_OS_MAC
|
||
#define _OS_APPLE_MAC 1
|
||
// Other kinds of Apple platforms
|
||
#else
|
||
# error "Unknown Apple platform"
|
||
#endif
|
||
#elif __linux__
|
||
#define _OS_LINUX 1
|
||
// linux
|
||
#elif __unix__ // all unices not caught above
|
||
#define _OS_UNIX 1
|
||
// Unix
|
||
#elif defined(_POSIX_VERSION)
|
||
#define _OS_POSIX 1
|
||
// POSIX
|
||
#else
|
||
# error "Unknown compiler"
|
||
#endif
|
||
|
||
#if _OS_WIN
|
||
#define WIN_PART 1
|
||
#elif _OS_LINUX
|
||
#define LINUX_PART 1
|
||
#else
|
||
#error "Not Supported Operator System"
|
||
#endif
|
||
|
||
#if WIN_PART
|
||
#include <winsock2.h>
|
||
#include <WS2tcpip.h>
|
||
#include <windows.h>
|
||
#define strcasecmp _stricmp
|
||
#define strncasecmp _strnicmp
|
||
#define socklen_t int
|
||
#elif LINUX_PART
|
||
#include <unistd.h>
|
||
#include <arpa/inet.h>
|
||
#include <pthread.h>
|
||
#include <strings.h>
|
||
#define SOCKET long long int
|
||
//#define INVALID_SOCKET (SOCKET)(~0)
|
||
#endif
|
||
|
||
#ifndef ZZY_SLEEP
|
||
#define ZZY_SLEEP
|
||
#if WIN_PART
|
||
#define sleeps(s) Sleep(s*1000)
|
||
#define sleepms(ms) Sleep(ms)
|
||
#elif LINUX_PART
|
||
#define sleeps(s) sleep(s)
|
||
#define sleepms(ms) usleep(ms*1000)
|
||
#endif
|
||
#endif
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
enum {
|
||
ERR_SOCK_SUCCESS,
|
||
ERR_SOCK_MALLOC,
|
||
ERR_SOCK_NULLPTR,
|
||
|
||
ERR_SOCK_WSAStartup,
|
||
ERR_SOCK_DETERMINE_AGREEMENT,
|
||
ERR_SOCK_CREATE_SOCKET,
|
||
ERR_SOCK_BIND,
|
||
ERR_SOCK_LISTEN,
|
||
ERR_SOCK_ACCEPT,
|
||
ERR_SOCK_CONNECT,
|
||
|
||
ERR_SOCK_ADDRINFO,
|
||
//getaddrinfo
|
||
ERR_SOCK_EAI_MAPPING_NOT_EXIST,
|
||
ERR_SOCK_EAI_AGAIN,
|
||
ERR_SOCK_EAI_BADFLAGS,
|
||
ERR_SOCK_EAI_FAIL,
|
||
ERR_SOCK_EAI_FAMILY,
|
||
ERR_SOCK_EAI_MEMORY,
|
||
ERR_SOCK_EAI_NONAME,
|
||
ERR_SOCK_EAI_SERVICE,
|
||
ERR_SOCK_EAI_SOCKTYPE,
|
||
};
|
||
|
||
static inline int make_sock(SOCKET* sock);
|
||
static inline int sock_connect(SOCKET sock, const char* connect_ip, unsigned short port);
|
||
static inline int sock_bindlisten(SOCKET sock, const char* server_ip, unsigned short port);
|
||
static inline int sock_accpet(SOCKET sock,SOCKET* client, char** accept_ip, unsigned short* port);
|
||
static inline int make_server_sock(SOCKET* sock, const char* server_ip, unsigned short port);
|
||
static inline int make_client_sock(SOCKET* sock, const char* connect_ip, unsigned short port);
|
||
static inline void close_sock(SOCKET sock);
|
||
static inline void out_sock_err(FILE* output, int errcode);
|
||
static inline void get_sock_err(char* buff_128, size_t buff_len, int errcode);
|
||
static inline void sock_thread(void(*thread_func)(void*), void* data);
|
||
|
||
#define _SOCKET_TEST_IP "127.0.0.1"
|
||
#define _SOCKET_TEST_PORT 6789
|
||
static inline int _socket(SOCKET* sock, const char* ip, const char* port);
|
||
static inline int _connect(SOCKET sock, const char* ip, const char* port);
|
||
static inline int _bind(SOCKET sock, const char* ip, const char* port);
|
||
static inline int _bindlisten(SOCKET sock, const char* ip, const char* port);
|
||
|
||
static inline int _sock(SOCKET* sock, int af, int type);
|
||
static inline int make_sock(SOCKET* sock) { return make_sock_tcp4(sock); };
|
||
static inline int make_sock_tcp4(SOCKET* sock) { return _sock(sock, AF_INET, SOCK_STREAM); }
|
||
static inline int make_sock_tcp6(SOCKET* sock) { return _sock(sock, AF_INET6, SOCK_STREAM); }
|
||
static inline int make_sock_udp4(SOCKET* sock) { return _sock(sock, AF_INET, SOCK_DGRAM); }
|
||
static inline int make_sock_udp6(SOCKET* sock) { return _sock(sock, AF_INET6, SOCK_DGRAM); }
|
||
|
||
static inline int _sock(SOCKET* sock, int af, int type) {
|
||
#ifdef WIN_PART
|
||
WSADATA wsaData;
|
||
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
|
||
return ERR_SOCK_WSAStartup;
|
||
}
|
||
|
||
if (HIBYTE(wsaData.wVersion) != 2 || \
|
||
LOBYTE(wsaData.wVersion) != 2) {
|
||
return ERR_SOCK_DETERMINE_AGREEMENT;
|
||
}
|
||
#endif
|
||
*sock = socket(af, type, 0);
|
||
if (*sock == INVALID_SOCKET) {
|
||
return ERR_SOCK_CREATE_SOCKET;
|
||
}
|
||
return ERR_SOCK_SUCCESS;
|
||
}
|
||
|
||
static inline int _sock_eai_res_map(int res) {
|
||
switch (res) {
|
||
case EAI_AGAIN: return ERR_SOCK_EAI_AGAIN;
|
||
case EAI_BADFLAGS: return ERR_SOCK_EAI_BADFLAGS;
|
||
case EAI_FAIL: return ERR_SOCK_EAI_FAIL;
|
||
case EAI_FAMILY: return ERR_SOCK_EAI_FAMILY;
|
||
case EAI_MEMORY: return ERR_SOCK_EAI_MEMORY;
|
||
case EAI_NONAME: return ERR_SOCK_EAI_NONAME;
|
||
case EAI_SERVICE: return ERR_SOCK_EAI_SERVICE;
|
||
case EAI_SOCKTYPE: return ERR_SOCK_EAI_SOCKTYPE;
|
||
default: return ERR_SOCK_EAI_MAPPING_NOT_EXIST;
|
||
}
|
||
}
|
||
|
||
static inline int _socket(SOCKET* sock, const char* ip, const char* port) {
|
||
struct addrinfo inf = { 0 };
|
||
struct addrinfo* res_addr = NULL;
|
||
int res = getaddrinfo(ip, port, &inf, &res_addr);
|
||
if (res != 0) {
|
||
return _sock_eai_res_map(res);
|
||
}
|
||
for (struct addrinfo* p = res_addr; p != NULL; p = p->ai_next) {
|
||
if (*sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) {
|
||
if (*sock == INVALID_SOCKET) {
|
||
return ERR_SOCK_CREATE_SOCKET;
|
||
}
|
||
freeaddrinfo(res_addr);
|
||
return ERR_SOCK_SUCCESS;
|
||
}
|
||
}
|
||
freeaddrinfo(res_addr);
|
||
return ERR_SOCK_CONNECT;
|
||
}
|
||
|
||
static inline int _connect(SOCKET sock, const char* ip, const char* port) {
|
||
struct addrinfo inf = { 0 };
|
||
struct addrinfo* res_addr = NULL;
|
||
int res = getaddrinfo(ip, port, &inf, &res_addr);
|
||
if (res != 0) {
|
||
return _sock_eai_res_map(res);
|
||
}
|
||
for (struct addrinfo* p = res_addr; p != NULL; p = p->ai_next) {
|
||
if (connect(sock, p->ai_addr, p->ai_addrlen) == 0) {
|
||
freeaddrinfo(res_addr);
|
||
return ERR_SOCK_SUCCESS;
|
||
}
|
||
}
|
||
freeaddrinfo(res_addr);
|
||
return ERR_SOCK_CONNECT;
|
||
}
|
||
|
||
static inline int _bind(SOCKET sock, const char* ip, const char* port) {
|
||
struct addrinfo inf = { 0 };
|
||
struct addrinfo* res_addr = NULL;
|
||
int res = getaddrinfo(ip, port, &inf, &res_addr);
|
||
if (res != 0) {
|
||
return ERR_SOCK_ADDRINFO;
|
||
}
|
||
for (struct addrinfo* p = res_addr; p != NULL; p = p->ai_next) {
|
||
if (bind(sock, p->ai_addr, p->ai_addrlen) == 0) {
|
||
freeaddrinfo(res_addr);
|
||
return ERR_SOCK_SUCCESS;
|
||
}
|
||
}
|
||
freeaddrinfo(res_addr);
|
||
return ERR_SOCK_CONNECT;
|
||
}
|
||
|
||
static inline int _bindlisten(SOCKET sock, const char* ip, const char* port) {
|
||
int res = _bind(sock, ip, port);
|
||
if(res == ERR_SOCK_SUCCESS){
|
||
if (listen(sock, SOMAXCONN) == 0) {
|
||
return ERR_SOCK_SUCCESS;
|
||
}
|
||
return ERR_SOCK_LISTEN;
|
||
}
|
||
return res;
|
||
}
|
||
|
||
static inline int sock_connect(SOCKET sock, const char* connect_ip, unsigned short port) {
|
||
char buf[8] = { 0 };
|
||
sprintf(buf, "%u", port);
|
||
return _connect(sock, connect_ip, buf);
|
||
}
|
||
|
||
static inline int sock_bindlisten(SOCKET sock, const char* server_ip, unsigned short port) {
|
||
char buf[8] = { 0 };
|
||
sprintf(buf, "%u", port);
|
||
return _bindlisten(sock, server_ip, buf);
|
||
}
|
||
|
||
static inline int sock_accpet(SOCKET sock,SOCKET* client, char** accept_ip, unsigned short* port) {
|
||
struct sockaddr_in caddr = { 0 };
|
||
socklen_t addrLen = sizeof(struct sockaddr_in);
|
||
|
||
if(client == NULL) {
|
||
return ERR_SOCK_NULLPTR;
|
||
}
|
||
*client = accept(sock,(struct sockaddr*) &caddr, &addrLen);
|
||
if (*client == -1) {
|
||
return ERR_SOCK_ACCEPT;
|
||
}
|
||
|
||
char* ip = (char*)malloc(32);
|
||
if(ip == NULL) {
|
||
return ERR_SOCK_MALLOC;
|
||
}
|
||
|
||
int buffLen = strlen( inet_ntoa(caddr.sin_addr) );
|
||
if(accept_ip != NULL) {
|
||
strncpy(ip, inet_ntoa(caddr.sin_addr), buffLen);
|
||
ip[buffLen] = '\0';
|
||
*accept_ip = ip;
|
||
}
|
||
if(port != NULL) {
|
||
*port = ntohs(caddr.sin_port);
|
||
}
|
||
|
||
return ERR_SOCK_SUCCESS;
|
||
}
|
||
|
||
static inline int make_server_sock(SOCKET* sock, const char* server_ip, unsigned short port) {
|
||
int res = make_sock(sock);
|
||
if(res != ERR_SOCK_SUCCESS) {
|
||
return res;
|
||
}
|
||
|
||
res = sock_bindlisten(*sock, server_ip, port);
|
||
if(res != ERR_SOCK_SUCCESS) {
|
||
return res;
|
||
}
|
||
|
||
return ERR_SOCK_SUCCESS;
|
||
}
|
||
|
||
static inline int make_client_sock(SOCKET* sock, const char* connect_ip, unsigned short port) {
|
||
int res = make_sock(sock);
|
||
if(res != ERR_SOCK_SUCCESS) {
|
||
return res;
|
||
}
|
||
|
||
if(connect_ip) {
|
||
res = sock_connect(*sock, connect_ip, port);
|
||
if(res != ERR_SOCK_SUCCESS) {
|
||
return res;
|
||
}
|
||
}
|
||
|
||
return ERR_SOCK_SUCCESS;
|
||
}
|
||
|
||
static inline void close_sock(SOCKET sock) {
|
||
if(sock == -1) {
|
||
return;
|
||
}
|
||
#if WIN_PART
|
||
closesocket(sock);
|
||
#elif LINUX_PART
|
||
close(sock);
|
||
#endif
|
||
}
|
||
|
||
static inline void out_sock_err(FILE* output, int errcode) {
|
||
fprintf(output, "%d", errcode);
|
||
}
|
||
|
||
static inline void get_sock_err(char* buff_128, size_t buff_len, int errcode) {
|
||
if(buff_len < 128) {
|
||
return;
|
||
}
|
||
// enum {
|
||
// ERR_SOCK_SUCCESS,
|
||
// ERR_SOCK_MALLOC,
|
||
// ERR_SOCK_NULLPTR,
|
||
// ERR_SOCK_WSAStartup,
|
||
// ERR_SOCK_DETERMINE_AGREEMENT,
|
||
// ERR_SOCK_CREATE_SOCKET,
|
||
// ERR_SOCK_BIND,
|
||
// ERR_SOCK_LISTEN,
|
||
// ERR_SOCK_ACCEPT,
|
||
|
||
// ERR_SOCK_CONNECT,
|
||
// };
|
||
//https://learn.microsoft.com/zh-cn/windows/win32/api/ws2tcpip/nf-ws2tcpip-getaddrinfo?redirectedfrom=MSDN
|
||
//<2F><><EFBFBD><EFBFBD>ֵ WSA <20><>Ч<EFBFBD><D0A7> ˵<><CBB5>
|
||
//EAI_AGAIN WSATRY_AGAIN <09><><EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD><EFBFBD>ʱʧ<CAB1>ܡ<EFBFBD>
|
||
//EAI_BADFLAGS WSAEINVAL Ϊ pHints <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ai_flags <20><>Ա<EFBFBD>ṩ<EFBFBD><E1B9A9><EFBFBD><EFBFBD>Чֵ<D0A7><D6B5>
|
||
//EAI_FAIL WSANO_RECOVERY <09><><EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD>з<EFBFBD><D0B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɻָ<C9BB><D6B8><EFBFBD>ʧ<EFBFBD>ܡ<EFBFBD>
|
||
//EAI_FAMILY WSAEAFNOSUPPORT <09><>֧<EFBFBD><D6A7> pHints <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ai_family <20><>Ա<EFBFBD><D4B1>
|
||
//EAI_MEMORY WSA_NOT_ENOUGH_MEMORY <09>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD>ܡ<EFBFBD>
|
||
//EAI_NONAME WSAHOST_NOT_FOUND <09><><EFBFBD>ṩ<EFBFBD>IJ<EFBFBD><C4B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><CEB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD>ṩ pNodeName <20><> pServiceName <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
//EAI_SERVICE WSATYPE_NOT_FOUND pHints <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>ai_socktype<70><65>Ա<EFBFBD><D4B1>֧<EFBFBD><D6A7> pServiceName <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
//EAI_SOCKTYPE WSAESOCKTNOSUPPORT <09><>֧<EFBFBD><D6A7> pHints <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ai_socktype <20><>Ա<EFBFBD><D4B1>
|
||
|
||
sprintf(buff_128, "%3d", errcode);
|
||
}
|
||
|
||
static inline void sock_thread(void(*thread_func)(void*), void* data) {
|
||
#if WIN_PART
|
||
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)thread_func, data, 0, NULL);
|
||
#elif LINUX_PART
|
||
pthread_t pid;
|
||
pthread_create(&pid, 0, (void*(*)(void*))thread_func, data);
|
||
#endif
|
||
}
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
|
||
|
||
#endif |