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; | ||
|  | } | ||
|  | 
 |