📄 socket.cpp
字号:
/******************************************************************************** socket.cpp: socket management*-------------------------------------------------------------------------------* (c)1999-2001 VideoLAN* $Id: socket.cpp,v 1.17 2002/10/07 15:01:21 sam Exp $** Authors: Benoit Steiner <benny@via.ecp.fr>* Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>** This program is free software; you can redistribute it and/or* modify it under the terms of the GNU General Public License* as published by the Free Software Foundation; either version 2* of the License, or (at your option) any later version.** This program is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the* GNU General Public License for more details.** You should have received a copy of the GNU General Public License* along with this program; if not, write to the Free Software* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.**-------------------------------------------------------------------------------* This class encapsulate the differences between the implementations of the* BSD sockets* TO DO: the gethostbyname function is not thread safe, protect it********************************************************************************///------------------------------------------------------------------------------// Preamble//------------------------------------------------------------------------------#include "defs.h"#include <string.h>#include <stdlib.h>#if defined WIN32#include <winsock2.h>#else#include <sys/time.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h> #include <netdb.h>#include <unistd.h> #include <errno.h>#endif#ifdef STRUCT_IOVEC_IN_SYS_UIO_H#include <sys/uio.h>#endif#include <stdio.h>#include "common.h"#include "debug.h"#include "string.h"#include "exception.h"#include "system.h"#include "vector.h" #include "socket.h"#include "vector.cpp"//------------------------------------------------------------------------------// Plateform specific issues//------------------------------------------------------------------------------#if defined WIN32# define ERR_INTR WSAEINTR#else# define ERR_INTR EINTR#endif//******************************************************************************// E_InetAddr class//******************************************************************************// //******************************************************************************E_InetAddr::E_InetAddr(const C_String& strMsg) : E_Exception(GetErrorCode(SYSTEM_NETWORK), strMsg){}E_InetAddr::E_InetAddr(const C_String& strMsg, const E_InetAddr& e) : E_Exception(GetErrorCode(SYSTEM_NETWORK), strMsg, e){}//******************************************************************************// E_Socket class//******************************************************************************// //******************************************************************************E_Socket::E_Socket(const C_String& strMsg) : E_Exception(GetErrorCode(SYSTEM_NETWORK), strMsg){}E_Socket::E_Socket(const C_String& strMsg, const E_Socket& e) : E_Exception(GetErrorCode(SYSTEM_NETWORK), strMsg, e){}E_Socket::E_Socket(const C_String& strMsg, const E_InetAddr& e) : E_Exception(GetErrorCode(SYSTEM_NETWORK), strMsg, e){}//******************************************************************************// C_SocketBuff class//******************************************************************************// //******************************************************************************//------------------------------------------------------------------------------// Constructor//------------------------------------------------------------------------------////------------------------------------------------------------------------------C_SocketBuff::C_SocketBuff(unsigned int iSlotCount){ m_iSlotCount = iSlotCount; m_pBuffers = new sock_buff[iSlotCount];}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------////------------------------------------------------------------------------------C_SocketBuff::~C_SocketBuff(){ ASSERT(m_pBuffers); delete[] m_pBuffers;}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------////------------------------------------------------------------------------------void C_SocketBuff::AssignSlot(unsigned int iSlot, char* pBuff, unsigned int iBuffSize){ ASSERT(iSlot < m_iSlotCount); ASSERT(pBuff); #ifdef STRUCT_IOVEC_IN_SYS_UIO_H m_pBuffers[iSlot].iov_base = pBuff; m_pBuffers[iSlot].iov_len = iBuffSize;#elif defined WIN32 m_pBuffers[iSlot].buf = pBuff; m_pBuffers[iSlot].len = iBuffSize;#endif}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------////------------------------------------------------------------------------------void C_SocketBuff::SetSlotBuff(unsigned int iSlot, char* pBuff){ ASSERT(iSlot < m_iSlotCount); ASSERT(pBuff); #ifdef STRUCT_IOVEC_IN_SYS_UIO_H m_pBuffers[iSlot].iov_base = pBuff;#elif defined WIN32 m_pBuffers[iSlot].buf = pBuff;#endif}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------////------------------------------------------------------------------------------void C_SocketBuff::SetSlotSize(unsigned int iSlot, unsigned int iBuffSize){ ASSERT(iSlot < m_iSlotCount); #ifdef STRUCT_IOVEC_IN_SYS_UIO_H m_pBuffers[iSlot].iov_len = iBuffSize;#elif defined WIN32 m_pBuffers[iSlot].len = iBuffSize;#endif}//******************************************************************************// C_Inet4Addr class//******************************************************************************// //******************************************************************************//------------------------------------------------------------------------------////------------------------------------------------------------------------------////------------------------------------------------------------------------------void C_Inet4Addr::Build(const C_String& strHost, const C_String& strPort){ // Init the structure memset(&m_sInetAddr, 0, sizeof(m_sInetAddr)); m_sInetAddr.sin_family = AF_INET; // Set the port field int iPort = strPort.ToInt(); if(iPort) { // Port is given by its number m_sInetAddr.sin_port = htons(iPort); } else { // It should be given by its service name struct servent* pPort = getservbyname(strPort.GetString(), NULL); if(pPort == NULL) { throw E_InetAddr("Unknown port: " + strPort); } else m_sInetAddr.sin_port = pPort->s_port; } // Set the address field // Assume the address is given in dotted-decimal format and try to convert m_sInetAddr.sin_addr.s_addr = inet_addr(strHost.GetString()); if(m_sInetAddr.sin_addr.s_addr==(u32)-1 && strHost.Find("255.255.255.255") < 0) { // Address should be given by a host name struct hostent* pHostEnt = gethostbyname(strHost.GetString()); if(pHostEnt == NULL) { throw E_InetAddr("Unknown host: " + strHost); } else memcpy(&m_sInetAddr.sin_addr, pHostEnt->h_addr, pHostEnt->h_length); }}//******************************************************************************// C_Inet4Addr class//******************************************************************************// //******************************************************************************//------------------------------------------------------------------------------////------------------------------------------------------------------------------////------------------------------------------------------------------------------#ifdef HAVE_IPV6void C_Inet6Addr::Build(const C_String& strHost, const C_String& strPort, int iType){ struct addrinfo sHints; sHints.ai_flags = 0; sHints.ai_family = AF_INET6; sHints.ai_socktype = iType; sHints.ai_protocol = 0; sHints.ai_addrlen = 0; sHints.ai_addr = NULL; sHints.ai_canonname = NULL; sHints.ai_next = NULL; struct addrinfo *pRes = NULL; int iRc = getaddrinfo(strHost.GetString(), strPort.GetString(), &sHints, &pRes); if(!iRc) { ASSERT(pRes->ai_family == AF_INET6); m_sInetAddr = *(sockaddr_in6*)(pRes->ai_addr); freeaddrinfo(pRes); } else { ASSERT(!pRes); throw E_InetAddr(C_String("Inet6 address error: ") + gai_strerror(iRc)); }}#endif//******************************************************************************// C_Socket class//******************************************************************************// //******************************************************************************//------------------------------------------------------------------------------// Constructor//------------------------------------------------------------------------------////------------------------------------------------------------------------------C_Socket::C_Socket(){ m_iDomain = AF_UNSPEC; ZERO(m_hSocket);}//------------------------------------------------------------------------------////------------------------------------------------------------------------------void C_Socket::Open(int iDomain, int iType, int iProtocol/* = 0*/){ m_iDomain = iDomain; m_iType = iType; m_hSocket = socket(m_iDomain, iType, iProtocol); if(m_hSocket < 0) { throw E_Socket("Unable to open socket: " + GetErrorMsg(SYSTEM_NETWORK)); }}//------------------------------------------------------------------------------////------------------------------------------------------------------------------void C_Socket::Close(){#if defined WIN32 int iRc = closesocket(m_hSocket);#else int iRc = close(m_hSocket);#endif if(iRc) throw E_Socket("Socket could not be closed properly: " + GetErrorMsg(SYSTEM_NETWORK));}//------------------------------------------------------------------------------////------------------------------------------------------------------------------int C_Socket::GetDomain(){ // returns the address family of this socket // or AF_UNSPEC (set in constructor) return m_iDomain;}//------------------------------------------------------------------------------////------------------------------------------------------------------------------void C_Socket::SetOption(int iLevel, int iOpt, const char* pOptVal, socklen_t iOptLen){ int iRc = setsockopt(m_hSocket, iLevel, iOpt, pOptVal, iOptLen); if(iRc) { throw E_Socket(C_String("Unable to change value for option ") + iOpt + ": " + GetErrorMsg(SYSTEM_NETWORK)); }}//------------------------------------------------------------------------------////------------------------------------------------------------------------------void C_Socket::GetOption(int iLevel, int iOpt, char* pOptVal, socklen_t* pOptLen){ int iRc = getsockopt(m_hSocket, iLevel, iOpt, pOptVal, pOptLen); if(iRc) { throw E_Socket(C_String("Unable to get value for option ") + iOpt + ": " + GetErrorMsg(SYSTEM_NETWORK)); }}//------------------------------------------------------------------------------////------------------------------------------------------------------------------void C_Socket::Bind(const C_String& strIntf, const C_String& strPort){ // Try to resolve the given address struct sockaddr* pAddr; int iAddrLen; if(m_iDomain == AF_INET) { C_Inet4Addr cIntfAddr; try { cIntfAddr.Build(strIntf, strPort); } catch(E_InetAddr e) { throw E_Socket("Unable to bind to " + strIntf + " on port " + strPort, e); } pAddr = (struct sockaddr*)cIntfAddr.GetInetAddr(); iAddrLen = sizeof(*cIntfAddr.GetInetAddr()); }#ifdef HAVE_IPV6 else if(m_iDomain == AF_INET6) { C_Inet6Addr cIntfAddr; try
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -