📄 socket.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 + -