⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 socket.cpp

📁 缓冲 缓冲 缓冲 缓冲 缓冲 缓冲
💻 CPP
字号:
// Socket.cpp: implementation of the Socket class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Socket.h"
#include <time.h>
//#include "stdinc.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//string Socket::udpServer;
//short Socket::udpPort;

#ifndef ENOTCONN
#define ENOTCONN 1
#endif

/*
#ifdef _DEBUG

SocketException::SocketException(int aError) throw() {
	error = "SocketException: " + errorToString(aError);
	dcdebug("Thrown: %s\n", error.c_str());
}

#else // _DEBUG


SocketException::SocketException(int aError) : Exception(errorToString(aError)) { }

#endif

Socket::Stats Socket::stats = { 0, 0 };

static const u_int32_t SOCKS_TIMEOUT = 30000;

string SocketException::errorToString(int aType,int aError) throw() {
	char *err;
	if(aType==(int)PSOCKET)
	{
	   string msg = 	
	}
	return msg;
}
*/

int Socket::totalDown = 0;
int Socket::totalUp = 0;

#define checkconnected() if(!isConnected()) throw SocketException("Not Connected"))


void Socket::create(socket_type aType /* = TYPE_TCP */) throw(SocketException) {
	if(sock != INVALID_SOCKET)
		disconnect();

	switch(aType) {
	case TYPE_TCP:
		sock = checksocket(socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
		break;
	case TYPE_UDP:
		sock = checksocket(socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP));
		break;
	default:
		dcasserta(0);
	}
	stype = aType;
	setBlocking(true);
}

void Socket::accept(const Socket& listeningSocket) throw(SocketException) {
	if(sock != INVALID_SOCKET) {
		disconnect();
	}
	sockaddr_in sock_addr;
	socklen_t sz = sizeof(sock_addr);

	sock = check(::accept(listeningSocket.sock, (sockaddr*)&sock_addr, &sz));
#ifdef _WIN32
	// Make sure we disable any inherited windows message things for this socket.
	::WSAAsyncSelect(sock, NULL, 0, 0);
#endif

	stype = TYPE_TCP;

	//setIp(inet_ntoa(sock_addr.sin_addr));
	connected = true;
	setBlocking(true);
}


void Socket::bind(unsigned short aPort, const string& aIp) throw (SocketException){
	sockaddr_in sock_addr;
		
	sock_addr.sin_family = AF_INET;
	sock_addr.sin_port = htons(aPort);
	if(aIp==LOCAL_MACHINE)
		sock_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	else
		sock_addr.sin_addr.s_addr = inet_addr(aIp.c_str());
	if(::bind(sock, (sockaddr *)&sock_addr, sizeof(sock_addr)) == SOCKET_ERROR) {
		char buf[24];
		sprintf(buf,"%d",getLastError());
		dcdebug("Bind failed, retrying with INADDR_ANY: %s\n", SocketException(buf).getError().c_str());
		sock_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	    check(::bind(sock, (sockaddr *)&sock_addr, sizeof(sock_addr)));
	}
}

void Socket::listen() throw(SocketException) {
	check(::listen(sock, 20));
	connected = true;
	status = OPEN;
}

void Socket::connect(const string& aAddr, unsigned short aPort) throw(SocketException) {
	sockaddr_in  serv_addr;

	if(sock == INVALID_SOCKET) {
		create(TYPE_TCP);
	}

	string addr = resolve(aAddr);

	memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_port = htons(aPort);
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_addr.s_addr = inet_addr(addr.c_str());

	if(check(::connect(sock,(sockaddr*)&serv_addr,sizeof(serv_addr)), true)!=SOCKET_ERROR)
	{
		connected = true;
		status = OPEN;
	}
	else
	{
		connected = false;
		status = CLOSED;
	}
	//setIp(addr);
}

namespace {
	inline u_int32_t timeLeft(u_int32_t start, u_int32_t timeout) {
		if(timeout == 0) {
			return 0;
		}			
		u_int32_t now = time(0);
		if(start + timeout < now)
			throw SocketException("Connection Time Out");
		return start + timeout - now;
	}
}

int Socket::getSocketOptInt(int option) throw(SocketException) {
	int val;
	socklen_t len = sizeof(val);
	check(::getsockopt(sock, SOL_SOCKET, option, (char*)&val, &len));
	return val;
}

void Socket::setSocketOpt(int option, int val) throw(SocketException) {
	int len = sizeof(val);
	check(::setsockopt(sock, SOL_SOCKET, option, (char*)&val, len));
}

int Socket::read(void* aBuffer, int aBufLen) throw(SocketException) {
	if(aBuffer==NULL||aBufLen<=0)return -1;
	int len = 0;
	if(stype == TYPE_TCP) {
		len = check(::recv(sock, (char*)aBuffer, aBufLen, 0), true);
	} else {
		dcassert(type == TYPE_UDP);
		len = check(::recvfrom(sock, (char*)aBuffer, aBufLen, 0,NULL,NULL), true);
	}
	if(len > 0) {
		//Socket::stats.totalDown += len;
		//dcdebug("In: %.*s\n", len, (char*)aBuffer);
	}
	return len;
}

int Socket::write(const void* aBuffer, int aLen) throw(SocketException) {
	if(aBuffer==NULL||aLen<=0)return -1;
	int i = check(::send(sock, (const char*)aBuffer, aLen, 0), true);
	if(i > 0) {
		Socket::totalUp += i;
//		dcdebug("Out: %.*s\n", i, (char*)aBuffer);
	}
	return i;
}


/**
 * Blocks until timeout is reached one of the specified conditions have been fulfilled
 * @param millis Max milliseconds to block.
 * @param waitFor WAIT_*** flags that set what we're waiting for, set to the combination of flags that
 *				  triggered the wait stop on return (==WAIT_NONE on timeout)
 * @return WAIT_*** ored together of the current state.
 * @throw SocketException Select or the connection attempt failed.
 */
int Socket::wait(u_int32_t millis, int waitFor) throw(SocketException) {
	timeval tv;
	fd_set rfd, wfd, efd;
	fd_set *rfdp = NULL, *wfdp = NULL;
	tv.tv_sec = millis/1000;
	tv.tv_usec = (millis%1000)*1000; 

	if(waitFor & WAIT_CONNECT) {
		dcassert(!(waitFor & WAIT_READ) && !(waitFor & WAIT_WRITE));

		FD_ZERO(&wfd);
		FD_ZERO(&efd);

		FD_SET(sock, &wfd);
		FD_SET(sock, &efd);
		check(select((int)(sock+1), NULL, &wfd, &efd, &tv));

		if(FD_ISSET(sock, &wfd) || FD_ISSET(sock, &efd)) {
			int y = 0;
			socklen_t z = sizeof(y);
			check(getsockopt(sock, SOL_SOCKET, SO_ERROR, (char*)&y, &z));

			if(y != 0)
			{
				char buf[24];
				sprintf(buf,"%d",y);
				throw SocketException(buf);
			}
			// No errors! We're connected (?)...
			return WAIT_CONNECT;
		}
		return 0;
	}

	if(waitFor & WAIT_READ) {
		dcassert(!(waitFor & WAIT_CONNECT));
		rfdp = &rfd;
		FD_ZERO(rfdp);
		FD_SET(sock, rfdp);
	}
	if(waitFor & WAIT_WRITE) {
		dcassert(!(waitFor & WAIT_CONNECT));
		wfdp = &wfd;
		FD_ZERO(wfdp);
		FD_SET(sock, wfdp);
	}
	waitFor = WAIT_NONE;
	check(select((int)(sock+1), rfdp, wfdp, NULL, &tv));

	if(rfdp && FD_ISSET(sock, rfdp)) {
		waitFor |= WAIT_READ;
	}
	if(wfdp && FD_ISSET(sock, wfdp)) {
		waitFor |= WAIT_WRITE;
	}

	return waitFor;
}

string Socket::resolve(const string& aDns) {
	sockaddr_in sock_addr;

	memset(&sock_addr, 0, sizeof(sock_addr));
	sock_addr.sin_port = 0;
	sock_addr.sin_family = AF_INET;
	sock_addr.sin_addr.s_addr = inet_addr(aDns.c_str());

	if (sock_addr.sin_addr.s_addr == INADDR_NONE) {   /* server address is a name or invalid */
		hostent* host;
		host = gethostbyname(aDns.c_str());
		if (host == NULL) {
			return Util::emptyString;
		}
		sock_addr.sin_addr.s_addr = *((u_int32_t*)host->h_addr);
		return inet_ntoa(sock_addr.sin_addr);
	} else {
		return aDns;
	}
}

string Socket::getLocalIp() throw() {
	if(sock == INVALID_SOCKET)
		return Util::emptyString;

	sockaddr_in sock_addr;
	socklen_t len = sizeof(sock_addr);
	if(getsockname(sock, (sockaddr*)&sock_addr, &len) == 0) {
		return inet_ntoa(sock_addr.sin_addr);
	}
	return Util::emptyString;
}

void Socket::shutdown() throw() {
	if(sock != INVALID_SOCKET)
		::shutdown(sock, 1);
}

void Socket::close() {
	if(sock != INVALID_SOCKET) {
#ifdef _WIN32
		::closesocket(sock);
#else
		::close(sock);
#endif
		connected = false;
		sock = INVALID_SOCKET;
		status = CLOSED;
	}
}

void Socket::disconnect() throw() {
	shutdown();
	close();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -