头文件SocketImpl.h
namespace LinWin
{
class CSocketImpl
{
private:
net_socket_fd m_sock;
bool m_bBlocking;
public:
CSocketImpl();
CSocketImpl(net_socket_fd sockfd);
CSocketImpl(const CSocketImpl& iml);
virtual ~CSocketImpl();
public:
virtual int Create(int af = AF_INET, int type = SOCK_STREAM, int proto = 0);
virtual void Close();
virtual int Bind(const CSocketAddress& address);
virtual int Listen(int backlog = 64);
virtual int Accept(CSocketImpl* connfd, CSocketAddress& clientAddr);
virtual int Connect(const CSocketAddress& addr);
virtual int SendBytes(const void* lpBuf, unsigned int lpLen, int flag = 0);
virtual int RecvBytes(void* lpBuf, unsigned int lpLen, int flag = 0);
virtual int SendBytesto(const void* lpBuf, unsigned int lpLen, const CSocketAddress& addr, int flag = 0);
virtual int RecvBytesfrom(void* lpBuf, unsigned int lpLen, CSocketAddress& addr, int flag = 0);
virtual int ShutdownReceive();
virtual int ShutdownSend();
virtual int Shutdown();
virtual int SetSendBufferSize(int size);
virtual int GetSendBufferSize(int& size);
virtual int SetReceiveBufferSize(int size);
virtual int GetReceiveBufferSize(int& size);
virtual int LocalAddress(CSocketAddress& localAddr);
virtual int RemoteAddress(CSocketAddress& remoteAddr);
virtual int Available(int& result);
int SetOption(int level, int option, int value);
int SetOption(int level, int option, unsigned value);
int SetOption(int level, int option, unsigned char value);
virtual int SetRawOption(int level, int option, const void* value, int length);
int GetOption(int level, int option, int& value);
int GetOption(int level, int option, unsigned& value);
int GetOption(int level, int option, unsigned char& value);
virtual int GetRawOption(int level, int option, void* value, int length);
int SetLinger(bool on, int seconds);
int GetLinger(bool& on, int& seconds);
int SetNoDelay(bool flag);
int GetNoDelay(bool& flag);
int SetKeepAlive(bool flag);
int GetKeepAlive(bool& flag);
int SetReuseAddress(bool flag);
int GetReuseAddress(bool& flag);
virtual int SetBlocking(bool flag);
virtual bool GetBlocking() const;
net_socket_fd Sockfd() const;
const net_socket_fd* Handle() const
{
return reinterpret_cast<const net_socket_fd*>(&m_sock);
}
int SocketError();
virtual int Ioctl(net_ioctl_request_t request, int& arg);
virtual int Ioctl(net_ioctl_request_t request, void* arg);
}
}
Socket网络编程最基本的操作都封装在这里了,随后再把扩展的加进来。net_socket_fd类型的定义是为了统一平台之间的差异,它的定义已在platform.h文件中更新(在之前博客中)。
SocketImpl.cpp文件
#include "SocketImpl.h"
LinWin::CSocketImpl::CSocketImpl() : m_sock(NET_INVALID_SOCKET), m_bBlocking(false)
{
}
LinWin::CSocketImpl::CSocketImpl(net_socket_fd sock) : m_sock(sock), m_bBlocking(false)
{
}
LinWin::CSocketImpl::CSocketImpl(const CSocketImpl& iml) : m_sock(iml.m_sock), m_bBlocking(iml.m_bBlocking)
{
}
LinWin::CSocketImpl::~CSocketImpl()
{
Close();
}
int LinWin::CSocketImpl::Create(int af /* = AF_INET */, int type /* = SOCK_STREAM */, int proto /* = 0 */)
{
m_sock = ::socket(af, type, proto);
return m_sock == NET_INVALID_SOCKET ? -1 : 0;
}
void LinWin::CSocketImpl::Close()
{
if (m_sock != NET_INVALID_SOCKET)
{
closesocket(m_sock);
m_sock = NET_INVALID_SOCKET;
}
}
int LinWin::CSocketImpl::Bind(const CSocketAddress& address)
{
if (m_sock == NET_INVALID_SOCKET)
return -2;
if (::bind(m_sock, reinterpret_cast<const struct sockaddr *>(address.GetAddress()), address.AddressLength()) != 0)
return -1;
return 0;
}
int LinWin::CSocketImpl::Listen(int backlog /* = 64 */)
{
if (m_sock == NET_INVALID_SOCKET)
return -2;
if (::listen(m_sock, backlog) != 0)
return -1;
return 0;
}
int LinWin::CSocketImpl::Accept(CSocketImpl* connfd, CSocketAddress& clientAddr)
{
if (m_sock == NET_INVALID_SOCKET || connfd == NULL)
return -2;
socklen_t salen = clientAddr.AddressLength();
connfd->m_sock = ::accept(m_sock, reinterpret_cast<struct sockaddr*>(clientAddr.GetAddress()), &salen);
if (connfd->m_sock == NET_INVALID_SOCKET)
return -1;
return 0;
}
int LinWin::CSocketImpl::Connect(const CSocketAddress& addr)
{
if (m_sock == NET_INVALID_SOCKET)
return -2;
if (::connect(m_sock, reinterpret_cast<const struct sockaddr *>(addr.GetAddress()), addr.AddressLength()) != 0)
return -1;
return 0;
}
int LinWin::CSocketImpl::SendBytes(const void* lpBuf, unsigned int lpLen, int flag)
{
return ::send(m_sock, reinterpret_cast<const char*>(lpBuf), lpLen, flag);
}
int LinWin::CSocketImpl::RecvBytes(void* lpBuf, unsigned int lpLen, int flag)
{
return ::recv(m_sock, reinterpret_cast<char*>(lpBuf), lpLen, flag);
}
int LinWin::CSocketImpl::SendBytesto(const void* lpBuf, unsigned int lpLen, const CSocketAddress& addr, int flag)
{
return ::sendto(m_sock, reinterpret_cast<const char*>(lpBuf), lpLen, flag,
reinterpret_cast<const struct sockaddr*>(addr.GetAddress()), addr.AddressLength());
}
int LinWin::CSocketImpl::RecvBytesfrom(void* lpBuf, unsigned int lpLen, CSocketAddress& addr, int flag)
{
socklen_t addrLen = addr.AddressLength();
return ::recvfrom(m_sock, reinterpret_cast<char*>(lpBuf), lpLen, flag,
reinterpret_cast<sockaddr*>(addr.GetAddress()), &addrLen);
}
int LinWin::CSocketImpl::ShutdownReceive()
{
return (::shutdown(m_sock, SD_RECEIVE) != 0) ? -1 : 0;
}
int LinWin::CSocketImpl::ShutdownSend()
{
return (::shutdown(m_sock, SD_SEND) != 0) ? -1 : 0;
}
int LinWin::CSocketImpl::Shutdown()
{
return (::shutdown(m_sock, SD_BOTH) != 0) ? -1 : 0;
}
int LinWin::CSocketImpl::SetSendBufferSize(int size)
{
return SetOption(SOL_SOCKET, SO_SNDBUF, size);
}
int LinWin::CSocketImpl::GetSendBufferSize(int& size)
{
return GetOption(SOL_SOCKET, SO_SNDBUF, size);
}
int LinWin::CSocketImpl::SetReceiveBufferSize(int size)
{
return SetOption(SOL_SOCKET, SO_RCVBUF, size);
}
int LinWin::CSocketImpl::GetReceiveBufferSize(int& size)
{
return GetOption(SOL_SOCKET, SO_RCVBUF, size);
}
int LinWin::CSocketImpl::LocalAddress(CSocketAddress& localAddr)
{
socklen_t saLen = sizeof(struct sockaddr_in);
int rc = ::getsockname(m_sock, reinterpret_cast<struct sockaddr*>(localAddr.GetAddress()), &saLen);
return rc != 0 ? -1 : 0;
}
int LinWin::CSocketImpl::RemoteAddress(CSocketAddress& remoteAddr)
{
socklen_t saLen = sizeof(struct sockaddr_in);
int rc = ::getpeername(m_sock, reinterpret_cast<struct sockaddr*>(remoteAddr.GetAddress()), &saLen);
return rc != 0 ? -1 : 0;
}
int LinWin::CSocketImpl::Available(int& result)
{
return Ioctl(FIONREAD, result);
}
int LinWin::CSocketImpl::SetOption(int level, int option, int value)
{
return SetRawOption(level, option, &value, sizeof(value));
}
int LinWin::CSocketImpl::SetOption(int level, int option, unsigned value)
{
return SetRawOption(level, option, &value, sizeof(value));
}
int LinWin::CSocketImpl::SetOption(int level, int option, unsigned char value)
{
return SetRawOption(level, option, &value, sizeof(value));
}
int LinWin::CSocketImpl::SetRawOption(int level, int option, const void* value, int length)
{
int rc = ::setsockopt(m_sock, level, option, reinterpret_cast<const char*>(value), (socklen_t)length);
return rc == -1 ? -1 : 0;
}
int LinWin::CSocketImpl::GetOption(int level, int option, int& value)
{
return GetRawOption(level, option, &value, sizeof(value));
}
int LinWin::CSocketImpl::GetOption(int level, int option, unsigned& value)
{
return GetRawOption(level, option, &value, sizeof(value));
}
int LinWin::CSocketImpl::GetOption(int level, int option, unsigned char& value)
{
return GetRawOption(level, option, &value, sizeof(value));
}
int LinWin::CSocketImpl::GetRawOption(int level, int option, void* value, int length)
{
int rc = ::getsockopt(m_sock, level, option, reinterpret_cast<char*>(value), reinterpret_cast<socklen_t*>(&length));
return rc == -1 ? -1 : 0;
}
int LinWin::CSocketImpl::SetLinger(bool on, int seconds)
{
struct linger l;
l.l_onoff = on ? 1 : 0;
l.l_linger = seconds;
return SetRawOption(SOL_SOCKET, SO_LINGER, &l, sizeof(l));
}
int LinWin::CSocketImpl::GetLinger(bool& on, int& seconds)
{
struct linger l;
int len = sizeof(l);
int ret = GetRawOption(SOL_SOCKET, SO_LINGER, &l, len);
if (ret == 0)
{
on = (l.l_onoff != 0);
seconds = l.l_linger;
}
return ret;
}
int LinWin::CSocketImpl::SetNoDelay(bool flag)
{
int value = flag ? 1 : 0;
return SetOption(IPPROTO_TCP, TCP_NODELAY, value);
}
int LinWin::CSocketImpl::GetNoDelay(bool& flag)
{
int value = 0;
int ret = GetOption(IPPROTO_TCP, TCP_NODELAY, value);
if (ret == 0)
flag = (value != 0);
return ret;
}
int LinWin::CSocketImpl::SetKeepAlive(bool flag)
{
int value = flag ? 1 : 0;
return SetOption(SOL_SOCKET, SO_KEEPALIVE, value);
}
int LinWin::CSocketImpl::GetKeepAlive(bool& flag)
{
int value(0);
int ret = GetOption(SOL_SOCKET, SO_KEEPALIVE, value);
if (ret == 0)
flag = (value != 0);
return ret;
}
int LinWin::CSocketImpl::SetReuseAddress(bool flag)
{
int value = flag ? 1 : 0;
return SetOption(SOL_SOCKET, SO_REUSEADDR, value);
}
int LinWin::CSocketImpl::GetReuseAddress(bool& flag)
{
int value(0);
int ret = GetOption(SOL_SOCKET, SO_REUSEADDR, value);
if (ret == 0)
flag = (value != 0);
return ret;
}
int LinWin::CSocketImpl::SetBlocking(bool flag)
{
#ifdef WINDOWS_FAMILY
unsigned long nonblocking = flag ? 1 : 0;
if (ioctlsocket(m_sock, FIONBIO, (unsigned long*)&nonblocking) == SOCKET_ERROR)
return -1;
#else
int opts;
opts = fcntl(m_sock, F_GETFL);
if (opts < 0)
return -1;
if (flag)
opts = opts | O_NONBLOCK;
else
opts = opts & (~O_NONBLOCK);
if (fcntl(m_sock, F_SETFL, opts) < 0)
return -1;
#endif
m_bBlocking = flag;
return 0;
}
bool LinWin::CSocketImpl::GetBlocking() const
{
return m_bBlocking;
}
net_socket_fd LinWin::CSocketImpl::Sockfd() const
{
return m_sock;
}
int LinWin::CSocketImpl::Ioctl(net_ioctl_request_t request, int& arg)
{
int rc;
#ifdef WINDOWS_FAMILY
rc = ioctlsocket(m_sock, request, reinterpret_cast<u_long*>(&arg));
#else
rc = ::ioctl(m_sock, request, &arg);
#endif
return (rc != 0) ? -1 : 0;
}
int LinWin::CSocketImpl::Ioctl(net_ioctl_request_t request, void* arg)
{
int rc;
#ifdef WINDOWS_FAMILY
rc = ioctlsocket(m_sock, request, reinterpret_cast<u_long*>(arg));
#else
rc = ::ioctl(m_sock, request, arg);
#endif
return (rc != 0) ? -1 : 0;
}
int LinWin::CSocketImpl::SocketError()
{
#ifdef WINDOWS_FAMILY
return GetLastError();
#else
return errno;
#endif
}
由于CSocketAddress类中添加了一个非const版本的GetAddress成员函数,所以去掉此类中所有const_cast的转换。