Files
ngrok-c/nonblocking.h
2021-08-22 23:22:57 +08:00

144 lines
4.1 KiB
C++

#ifndef NONBLOCKING_H_INCLUDED
#define NONBLOCKING_H_INCLUDED
#include "config.h"
#include <string.h>
#if WIN32
#include <winsock.h>
#include <winsock2.h>
#include <windows.h>
#else
#include <fcntl.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#endif
#include <list>
#include "sslbio.h"
using namespace std;
#if WIN32
struct tcp_keepalive
{
u_long onoff;
u_long keepalivetime;
u_long keepaliveinterval;
};
#define SIO_RCVALL _WSAIOW(IOC_VENDOR, 1)
#define SIO_RCVALL_MCAST _WSAIOW(IOC_VENDOR, 2)
#define SIO_RCVALL_IGMPMCAST _WSAIOW(IOC_VENDOR, 3)
#define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR, 4)
#define SIO_ABSORB_RTRALERT _WSAIOW(IOC_VENDOR, 5)
#define SIO_UCAST_IF _WSAIOW(IOC_VENDOR, 6)
#define SIO_LIMIT_BROADCASTS _WSAIOW(IOC_VENDOR, 7)
#define SIO_INDEX_BIND _WSAIOW(IOC_VENDOR, 8)
#define SIO_INDEX_MCASTIF _WSAIOW(IOC_VENDOR, 9)
#define SIO_INDEX_ADD_MCAST _WSAIOW(IOC_VENDOR, 10)
#define SIO_INDEX_DEL_MCAST _WSAIOW(IOC_VENDOR, 11)
#define RCVALL_OFF 0
#define RCVALL_ON 1
#define RCVALL_SOCKETLEVELONLY 2
inline int SetKeepAlive(int sock)
{
BOOL bKeepAlive = TRUE;
int nRet = setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&bKeepAlive, sizeof(bKeepAlive));
if (nRet == SOCKET_ERROR)
{
return -1;
}
// 设置KeepAlive参数
tcp_keepalive alive_in = {0};
tcp_keepalive alive_out = {0};
alive_in.keepalivetime = 60000; // 开始首次KeepAlive探测前的TCP空闭时间
alive_in.keepaliveinterval = 60000; // 两次KeepAlive探测间的时间间隔
alive_in.onoff = TRUE;
unsigned long ulBytesReturn = 0;
//nRet = WSAIoctl(sock, SIO_KEEPALIVE_VALS, &alive_in, sizeof(alive_in),&alive_out, sizeof(alive_out), &ulBytesReturn, NULL, NULL);
if (nRet == SOCKET_ERROR)
{
return -1;
}
return 0;
}
#else
#include <netinet/in.h>
#include <netinet/tcp.h>
inline int SetKeepAlive(int sock)
{
/*有人说是秒单位。。有人说是毫秒单位*/
int keepalive = 1; // 开启keepalive属性
int keepidle = 60000; // 如该连接在60秒内没有任何数据往来,则进行探测
int keepinterval = 60000; // 探测时发包的时间间隔为5 秒
int keepcount = 1; // 探测尝试的次数.如果第1次探测包就收到响应了,则后2次的不再发.
setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepalive, sizeof(keepalive));
setsockopt(sock, SOL_TCP, TCP_KEEPIDLE, (void *)&keepidle, sizeof(keepidle));
setsockopt(sock, SOL_TCP, TCP_KEEPINTVL, (void *)&keepinterval, sizeof(keepinterval));
setsockopt(sock, SOL_TCP, TCP_KEEPCNT, (void *)&keepcount, sizeof(keepcount));
return 0;
}
#endif // WIN32
inline int setnonblocking(int sServer, int _nMode)
{
#if WIN32
DWORD nMode = _nMode;
return ioctlsocket(sServer, FIONBIO, &nMode);
#else
if (_nMode == 1)
{
return fcntl(sServer, F_SETFL, O_NONBLOCK);
}
else
{
return fcntl(sServer, F_SETFL, _nMode);
}
#endif
}
inline int net_dns(struct sockaddr_in *server_addr, const char *host, int port)
{
struct hostent *server_host;
if ((server_host = gethostbyname(host)) == NULL)
{
return -1;
}
memcpy((void *)&server_addr->sin_addr, (void *)server_host->h_addr, server_host->h_length);
server_addr->sin_family = AF_INET;
server_addr->sin_port = htons(port);
return 0;
}
inline int check_sock(int sock)
{
int error = -1;
#if WIN32
int len;
#else
socklen_t len;
#endif
len = sizeof(error);
getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&error, &len);
return error;
}
void clearsock(Sockinfo *sock_info);
inline int SetBufSize(int sock)
{
//接收缓冲区
int opt = 25 * 1024; //30K
setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (const char *)&opt, sizeof(opt));
//发送缓冲区 (这个千万不要。。发送不需要缓存区)
// setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (const char*)&opt,sizeof(opt));
return 0;
}
#endif // NONBLOCKING_H_INCLUDED