194 lines
4.7 KiB
C++
194 lines
4.7 KiB
C++
// PHZ
|
|
// 2018-5-15
|
|
|
|
#include "SocketUtil.h"
|
|
#include "Socket.h"
|
|
#include <iostream>
|
|
|
|
using namespace xop;
|
|
|
|
bool SocketUtil::Bind(SOCKET sockfd, std::string ip, uint16_t port)
|
|
{
|
|
struct sockaddr_in addr = {0};
|
|
addr.sin_family = AF_INET;
|
|
addr.sin_addr.s_addr = inet_addr(ip.c_str());
|
|
addr.sin_port = htons(port);
|
|
|
|
if(::bind(sockfd, (struct sockaddr*)&addr, sizeof addr) == SOCKET_ERROR) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void SocketUtil::SetNonBlock(SOCKET fd)
|
|
{
|
|
#if defined(__linux) || defined(__linux__)
|
|
int flags = fcntl(fd, F_GETFL, 0);
|
|
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
|
|
#else
|
|
unsigned long on = 1;
|
|
ioctlsocket(fd, FIONBIO, &on);
|
|
#endif
|
|
}
|
|
|
|
void SocketUtil::SetBlock(SOCKET fd, int write_timeout)
|
|
{
|
|
#if defined(__linux) || defined(__linux__)
|
|
int flags = fcntl(fd, F_GETFL, 0);
|
|
fcntl(fd, F_SETFL, flags&(~O_NONBLOCK));
|
|
#elif defined(WIN32) || defined(_WIN32)
|
|
unsigned long on = 0;
|
|
ioctlsocket(fd, FIONBIO, &on);
|
|
#else
|
|
#endif
|
|
if(write_timeout > 0)
|
|
{
|
|
#ifdef SO_SNDTIMEO
|
|
#if defined(__linux) || defined(__linux__)
|
|
struct timeval tv = {write_timeout/1000, (write_timeout%1000)*1000};
|
|
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof tv);
|
|
#elif defined(WIN32) || defined(_WIN32)
|
|
unsigned long ms = (unsigned long)write_timeout;
|
|
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&ms, sizeof(unsigned long));
|
|
#else
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void SocketUtil::SetReuseAddr(SOCKET sockfd)
|
|
{
|
|
int on = 1;
|
|
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof on);
|
|
}
|
|
|
|
void SocketUtil::SetReusePort(SOCKET sockfd)
|
|
{
|
|
#ifdef SO_REUSEPORT
|
|
int on = 1;
|
|
setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, (const char*)&on, sizeof(on));
|
|
#endif
|
|
}
|
|
|
|
void SocketUtil::SetNoDelay(SOCKET sockfd)
|
|
{
|
|
#ifdef TCP_NODELAY
|
|
int on = 1;
|
|
int ret = setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&on, sizeof(on));
|
|
#endif
|
|
}
|
|
|
|
void SocketUtil::SetKeepAlive(SOCKET sockfd)
|
|
{
|
|
int on = 1;
|
|
setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof(on));
|
|
}
|
|
|
|
void SocketUtil::SetNoSigpipe(SOCKET sockfd)
|
|
{
|
|
#ifdef SO_NOSIGPIPE
|
|
int on = 1;
|
|
setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (char *)&on, sizeof(on));
|
|
#endif
|
|
}
|
|
|
|
void SocketUtil::SetSendBufSize(SOCKET sockfd, int size)
|
|
{
|
|
setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&size, sizeof(size));
|
|
}
|
|
|
|
void SocketUtil::SetRecvBufSize(SOCKET sockfd, int size)
|
|
{
|
|
setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (char *)&size, sizeof(size));
|
|
}
|
|
|
|
std::string SocketUtil::GetPeerIp(SOCKET sockfd)
|
|
{
|
|
struct sockaddr_in addr = { 0 };
|
|
socklen_t addrlen = sizeof(struct sockaddr_in);
|
|
if (getpeername(sockfd, (struct sockaddr *)&addr, &addrlen) == 0)
|
|
{
|
|
return inet_ntoa(addr.sin_addr);
|
|
}
|
|
return "0.0.0.0";
|
|
}
|
|
|
|
std::string SocketUtil::GetSocketIp(SOCKET sockfd)
|
|
{
|
|
struct sockaddr_in addr = {0};
|
|
char str[INET_ADDRSTRLEN] = "127.0.0.1";
|
|
if (GetSocketAddr(sockfd, &addr) == 0) {
|
|
inet_ntop(AF_INET, &addr.sin_addr, str, sizeof(str));
|
|
}
|
|
return str;
|
|
}
|
|
|
|
int SocketUtil::GetSocketAddr(SOCKET sockfd, struct sockaddr_in* addr)
|
|
{
|
|
socklen_t addrlen = sizeof(struct sockaddr_in);
|
|
return getsockname(sockfd, (struct sockaddr*)addr, &addrlen);
|
|
}
|
|
|
|
uint16_t SocketUtil::GetPeerPort(SOCKET sockfd)
|
|
{
|
|
struct sockaddr_in addr = { 0 };
|
|
socklen_t addrlen = sizeof(struct sockaddr_in);
|
|
if (getpeername(sockfd, (struct sockaddr *)&addr, &addrlen) == 0)
|
|
{
|
|
return ntohs(addr.sin_port);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int SocketUtil::GetPeerAddr(SOCKET sockfd, struct sockaddr_in *addr)
|
|
{
|
|
socklen_t addrlen = sizeof(struct sockaddr_in);
|
|
return getpeername(sockfd, (struct sockaddr *)addr, &addrlen);
|
|
}
|
|
|
|
void SocketUtil::Close(SOCKET sockfd)
|
|
{
|
|
#if defined(__linux) || defined(__linux__)
|
|
::close(sockfd);
|
|
#elif defined(WIN32) || defined(_WIN32)
|
|
::closesocket(sockfd);
|
|
#endif
|
|
}
|
|
|
|
bool SocketUtil::Connect(SOCKET sockfd, std::string ip, uint16_t port, int timeout)
|
|
{
|
|
bool is_connected = true;
|
|
|
|
if (timeout > 0) {
|
|
SocketUtil::SetNonBlock(sockfd);
|
|
}
|
|
|
|
struct sockaddr_in addr = { 0 };
|
|
socklen_t addrlen = sizeof(addr);
|
|
addr.sin_family = AF_INET;
|
|
addr.sin_port = htons(port);
|
|
addr.sin_addr.s_addr = inet_addr(ip.c_str());
|
|
|
|
if (::connect(sockfd, (struct sockaddr*)&addr, addrlen) == SOCKET_ERROR) {
|
|
if (timeout > 0) {
|
|
is_connected = false;
|
|
fd_set fd_write;
|
|
FD_ZERO(&fd_write);
|
|
FD_SET(sockfd, &fd_write);
|
|
struct timeval tv = { timeout / 1000, timeout % 1000 * 1000 };
|
|
select((int)sockfd + 1, NULL, &fd_write, NULL, &tv);
|
|
if (FD_ISSET(sockfd, &fd_write)) {
|
|
is_connected = true;
|
|
}
|
|
SocketUtil::SetBlock(sockfd);
|
|
}
|
|
else {
|
|
is_connected = false;
|
|
}
|
|
}
|
|
|
|
return is_connected;
|
|
}
|
|
|