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

📄 socket.cpp

📁 跨操作系统的微型中间件
💻 CPP
字号:
#include <string.h>#ifndef __Win32__#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <sys/uio.h>#include <unistd.h>#include <netinet/tcp.h>#include <fcntl.h>#endif#include <errno.h>#include "OS.h"#include "Socket.h"#include "SocketUtils.h"#include "OSThread.h"#include "MyAssert.h"#ifdef USE_NETLOG#include <netlog.h>#endif#define INVALID_FD	(-1)Socket::Socket():   fState(kBlockingSocketType),//    fLocalAddrStrPtr(NULL),//   fLocalDNSStrPtr(NULL),    fPortStr(fPortBuffer, kPortBufSizeInBytes){	fFileDesc = INVALID_FD;    fLocalAddr.sin_addr.s_addr = 0;    fLocalAddr.sin_port = 0;    fDestAddr.sin_addr.s_addr = 0;    fDestAddr.sin_port = 0;   }Socket::~Socket(){	Close();}void Socket::Initialize(){#ifdef __Win32__    // Start Win32 DLLs    WORD wsVersion = MAKEWORD(1, 1);    WSADATA wsData;    (void)::WSAStartup(wsVersion, &wsData);#else#endif}void Socket::Uninitialize(){#ifdef __Win32__	WSACleanup();#else#endif}OS_Error Socket::Open(int theType){	Close();		if(fFileDesc == INVALID_FD)	{		fFileDesc = ::socket(PF_INET, theType, 0);		if (fFileDesc == kInvalidFileDesc)		{			Int32 ErrNo = (OS_Error)OS::GetErrno();			return ErrNo;		}#ifdef __Win32__		//set default send and receive buffer size		SetSocketBufSize(32*1024);		SetSocketRcvBufSize(32*1024);#endif	}          return OS_NoErr;}void Socket::Close(){	if(fFileDesc != INVALID_FD)	{#ifdef __Win32__		::closesocket(fFileDesc);#else		//::shutdown(fFileDesc,SHUT_RDWR);		::close(fFileDesc);#endif		fFileDesc = INVALID_FD;	}}void Socket::ReuseAddr(){    int one = 1;    int err = ::setsockopt(fFileDesc, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(int));    Assert(err == 0);   }void Socket::NoDelay(){    int one = 1;    int err = ::setsockopt(fFileDesc, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof(int));    Assert(err == 0);   }void Socket::KeepAlive(){    int one = 1;    int err = ::setsockopt(fFileDesc, SOL_SOCKET, SO_KEEPALIVE, (char*)&one, sizeof(int));    Assert(err == 0);   }void    Socket::SetSocketBufSize(UInt32 inNewSize){    int bufSize = inNewSize;    int err = ::setsockopt(fFileDesc, SOL_SOCKET, SO_SNDBUF, (char*)&bufSize, sizeof(int));    Assert(err == 0);}OS_Error    Socket::SetSocketRcvBufSize(UInt32 inNewSize){    int bufSize = inNewSize;    int err = ::setsockopt(fFileDesc, SOL_SOCKET, SO_RCVBUF, (char*)&bufSize, sizeof(int));    if (err == -1)        return OS::GetErrno();    return OS_NoErr;}OS_Error Socket::Bind(UInt32 addr, UInt16 port){#ifndef USE_NETLOG#if defined(__Win32__)    // missing from some platform includes    typedef int socklen_t;#endif#endif    socklen_t len = sizeof(fLocalAddr);    ::memset(&fLocalAddr, 0, sizeof(fLocalAddr));    fLocalAddr.sin_family = AF_INET;    fLocalAddr.sin_port = htons(port);    fLocalAddr.sin_addr.s_addr = htonl(addr);    int err = ::bind(fFileDesc, (sockaddr *)&fLocalAddr, sizeof(fLocalAddr));    if (err == -1)    {        fLocalAddr.sin_port = 0;        fLocalAddr.sin_addr.s_addr = 0;        return (OS_Error)OS::GetErrno();    }    else 
		::getsockname(fFileDesc, (sockaddr *)&fLocalAddr, &len); // get the kernel to fill in unspecified values   	fState |= kBound;    return OS_NoErr;}std::string Socket::GetLocalAddrStr(){	string strTmp;	SocketUtils::ConvertAddrToString(fLocalAddr.sin_addr, &strTmp);	return strTmp;}OS_Error Socket::Send(const char* inData, const UInt32 inLength, UInt32* outLengthSent,UInt32 vTimeOut){	Assert(inData != NULL);		if (!(fState & kConnected))	return (OS_Error)ENOTCONN;	//timout calc	int err = 0;	if(vTimeOut != 0)	{		struct timeval val;		val.tv_sec = 0;		val.tv_usec = vTimeOut * 1000;				fd_set TmpSet;		FD_ZERO(&TmpSet);		FD_SET(fFileDesc,&TmpSet);		err = select(fFileDesc+1, NULL,&TmpSet, NULL, &val);		if(err <=0 )		{			if(err == 0) err = EAGAIN;			return err;		}	}	//send	do 	{		err = ::send(fFileDesc, inData, inLength, 0);//flags??	} while((err == -1) && (OS::GetErrno() == EINTR));		if (err == -1)	{		//Are there any errors that can happen if the client is connected?		//Yes... EAGAIN. Means the socket is now flow-controleld		int theErr = OS::GetErrno();		if ((theErr != EAGAIN) && (this->IsConnected()))			fState ^= kConnected;//turn off connected state flag				return (OS_Error)theErr;	}		*outLengthSent = err;	return OS_NoErr;}OS_Error Socket::WriteV(const struct iovec* iov, const UInt32 numIOvecs, UInt32* outLenSent,UInt32 vTimeOut){    Assert(iov != NULL);    if (!(fState & kConnected))        return (OS_Error)ENOTCONN;	//timout calc	int err = 0;	if(vTimeOut != 0)	{		struct timeval val;		val.tv_sec = 0;		val.tv_usec = vTimeOut * 1000;				fd_set TmpSet;		FD_ZERO(&TmpSet);		FD_SET(fFileDesc,&TmpSet);		err = select(fFileDesc+1, NULL,&TmpSet, NULL, &val);		if(err <=0 )		{			if(err == 0) err = EAGAIN;			return err;		}	}    do    {#ifdef __Win32__        DWORD theBytesSent = 0;        err = ::WSASend(fFileDesc, (LPWSABUF)iov, numIOvecs, &theBytesSent, 0, NULL, NULL);        if (err == 0)            err = theBytesSent;#else       err = ::writev(fFileDesc, iov, numIOvecs);//flags??#endif    } while((err == -1) && (OS::GetErrno() == EINTR));    if (err == -1)    {        // Are there any errors that can happen if the client is connected?        // Yes... EAGAIN. Means the socket is now flow-controleld        int theErr = OS::GetErrno();        if ((theErr != EAGAIN) && (this->IsConnected()))            fState ^= kConnected;//turn off connected state flag        return (OS_Error)theErr;    }    *outLenSent = (UInt32)err;    return OS_NoErr;}OS_Error Socket::Peek(void *buffer, const UInt32 length, UInt32 *outRecvLenP){	Assert(outRecvLenP != NULL);    Assert(buffer != NULL);	    if (!(fState & kConnected))        return (OS_Error)ENOTCONN;	    //int theRecvLen = ::recv(fFileDesc, buffer, length, 0);//flags??    int theRecvLen;    do {		theRecvLen = ::recv(fFileDesc, (char*)buffer, length, MSG_PEEK);//flags??    } while((theRecvLen == -1) && (OS::GetErrno() == EINTR));	    if (theRecvLen == -1)    {        // Are there any errors that can happen if the client is connected?        // Yes... EAGAIN. Means the socket is now flow-controleld        int theErr = OS::GetErrno();        if ((theErr != EAGAIN ) && (this->IsConnected()))            fState ^= kConnected;//turn off connected state flag		        return (OS_Error)theErr;    }    //if we get 0 bytes back from read, that means the client has disconnected.    //Note that and return the proper error to the caller    else if (theRecvLen == 0)    {        fState ^= kConnected;        return (OS_Error)ENOTCONN;    }    Assert(theRecvLen > 0);    *outRecvLenP = (UInt32)theRecvLen;    return OS_NoErr;}OS_Error Socket::Read(void *buffer, const UInt32 length, UInt32 *outRecvLenP){    Assert(outRecvLenP != NULL);    Assert(buffer != NULL);    if (!(fState & kConnected))        return (OS_Error)ENOTCONN;    //int theRecvLen = ::recv(fFileDesc, buffer, length, 0);//flags??    int theRecvLen;    do {       theRecvLen = ::recv(fFileDesc, (char*)buffer, length, 0);//flags??    } while((theRecvLen == -1) && (OS::GetErrno() == EINTR));    if (theRecvLen == -1)    {        // Are there any errors that can happen if the client is connected?        // Yes... EAGAIN. Means the socket is now flow-controleld        int theErr = OS::GetErrno();        if ((theErr != EAGAIN ) && (this->IsConnected()))            fState ^= kConnected;//turn off connected state flag        return (OS_Error)theErr;    }    //if we get 0 bytes back from read, that means the client has disconnected.    //Note that and return the proper error to the caller    else if (theRecvLen == 0)    {        fState ^= kConnected;        return (OS_Error)ENOTCONN;    }    Assert(theRecvLen > 0);    *outRecvLenP = (UInt32)theRecvLen;    return OS_NoErr;}OS_Error Socket::SetNonBlocking(){#ifdef __Win32__    u_long one = 1;    int err = ::ioctlsocket(fFileDesc, FIONBIO, &one);#else    int flag = ::fcntl(fFileDesc, F_GETFL, 0);    int err = ::fcntl(fFileDesc, F_SETFL, flag | O_NONBLOCK);#endif	return err;}OS_Error Socket::SetBlocking(){#ifdef __Win32__    u_long one = 0;    int err = ::ioctlsocket(fFileDesc, FIONBIO, &one);#else    int flag = ::fcntl(fFileDesc, F_GETFL, 0);    int err = ::fcntl(fFileDesc, F_SETFL, flag & ~O_NONBLOCK);#endif		return err;}

⌨️ 快捷键说明

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