/************************************************************************/ /* Copyright (C), 2016-2020, [IT], 保留所有权利; /* 模 块 名:SocketHandle; /* 描 述:Socket Communication Classes; /* /* 版 本:[V 1.4] IPv6 support; /* 版 本:[V 1.3] Update for Asynchronous mode / Linux port; /* 版 本:[V 1.2] Update interface for TCP remote connection; /* 版 本:[V 1.1] Added multicast support; /* 作 者:[IT]; /* 日 期:[2/23/2016]; /* /* /* 注 意:; /* /* 修改记录:[IT]; /* 修改日期:; /* 修改版本:; /* 修改内容:; /************************************************************************/ #ifndef __SOCKETHANDLE_20160228__ #define __SOCKETHANDLE_20160228__ #pragma once #ifdef WIN32 #include #include #elif BSD_SOCKET #include "platform.h" #endif /************************************************************************/ /* Copyright (C), 2016-2020, [IT], 保留所有权利; /* 模 块 名:SockAddrIn; /* 描 述:SockAddrIn结构体,内部封装了 SOCKADDR_STORAGE (IPv4: SOCKADDR_IN, IPv6: SOCKADDR_IN6) 结构体; /* /* // IPV4地址结构; /* struct SOCKADDR_IN{ /* SHORT sin_family; // 地址簇; /* USHORT sin_port; // 端口号; /* in_addr sin_addr; // 地址; /* CHAR sin_zero[8]; // IPV4为了填充结构体来保持固定大小,无意义; /* }; /* /* struct IN_ADDR{ /* unsigned long s_addr; // 地址; /* }; /* /* // IPV6地址结构; /* struct SOCKADDR_IN6{ /* USHORT sin6_family; // 地址簇类型:AF_INET6; /* USHORT sin6_port; // 16位端口号; /* ULONG sin6_flowinfo; // 32位流标签; /* in6_addr sin6_addr; // 128位IP地址; /* union /* { /* ULONG sin6_scope_id; // Set of interfaces for a scope. /* SCOPE_ID sin6_scope_struct; /* }; /* }; /* /* struct in6_addr { /* union { /* UCHAR Byte[16]; /* USHORT Word[8]; /* } u; /* } ; /* /* typedef struct { /* union { /* struct /* { /* ULONG Zone : 28; /* ULONG Level : 4; /* }; /* ULONG Value; /* }; /* } SCOPE_ID, *PSCOPE_ID; /* /* 版 本:[V]; /* 作 者:[IT]; /* 日 期:[2/23/2016]; /* /* /* 注 意:; /* /* 修改记录:[IT]; /* 修改日期:; /* 修改版本:; /* 修改内容:; /************************************************************************/ struct SockAddrIn : public sockaddr_storage { public: SockAddrIn(); ~SockAddrIn(); // 拷贝构造; SockAddrIn(IN const SockAddrIn& sin); // 复制函数; SockAddrIn& Copy(IN const SockAddrIn& sin); // 清空结构体; void Clear(); // 对比地址是否相同; bool IsEqual(IN const SockAddrIn& sin) const; // 如果NULLAddr无效,返回TRUE; bool IsNull() const { return IsEqual(NULLAddr); } // 返回地址簇类型; short GetFamily() const { return ss_family; } // 返回IPV4网络地址; ULONG GetIPAddr() const { return ((SOCKADDR_IN*)this)->sin_addr.s_addr; } // 获取网络端口; short GetPort() const { return ((SOCKADDR_IN*)this)->sin_port; } // 创建服务端地址(同时支持IPV4和IPV6); bool CreateFrom(IN LPCTSTR pszAddr, IN LPCTSTR pszService, IN int nFamily = AF_INET); // 创建服务端地址(只支持IPV4); bool CreateFrom(IN ULONG lIPAddr, IN USHORT nPort, IN int nFamily = AF_INET, IN bool bFmtHost = true); // 赋值拷贝函数,返回this指针引用; SockAddrIn& operator=(const SockAddrIn& sin) { return Copy( sin ); } // 相等操作判断,相等返回TRUE; bool operator==(const SockAddrIn& sin) const { return IsEqual( sin ); } // 不等操作判断,如果不同返回TRUE; bool operator!=(const SockAddrIn& sin) const { return !IsEqual( sin ); } // 转换SOCKADDR地址,返回SOCKADDR格式的this对象; operator LPSOCKADDR() { return reinterpret_cast(this); } // 转换PIN6_ADDR地址,返回PIN6_ADDR格式的this对象; operator const IN6_ADDR*() const { return reinterpret_cast(this); } // 转换PIN6_ADDR地址,返回PIN6_ADDR格式的this对象; operator PIN6_ADDR() { return reinterpret_cast(this); } // 返回结构体(SOCKADDR_IN) 或 (SOCKADDR_STORAGE)的大小(由地址协议簇决定); size_t Size() const { return (ss_family == AF_INET) ? sizeof(sockaddr_in) : sizeof(sockaddr_storage); } // 以SOCKADDR_IN结构体来初始化this对象; void SetAddr(const sockaddr_in* psin) { SetAddr(reinterpret_cast(psin)); } // 以SOCKADDR_IN6结构体来初始化this对象; void SetAddr(const sockaddr_in6* psin) { SetAddr(reinterpret_cast(psin)); } // 以SOCKADDR_STROAGE结构体来初始化this对象; void SetAddr(const sockaddr_storage* pss) { ss_family = pss->ss_family; memcpy(this, pss, Size()); } static SockAddrIn NULLAddr; // 空地址; }; #ifdef WIN32 typedef LPWSAOVERLAPPED_COMPLETION_ROUTINE LPWSACOMPLETIONROUTINE; #endif // Jeff.add.2014.08.07-------------------------------------------------------- #define SOCKET_SERVER_PORT 6432 // Jeff.注意, 这里单个包的大小不能超过该设置数值,一般设置为10*1024即10KB; 不过实际中可根据实际情况处理,如使用TCP来传输数据的话; #define SOCKET_BUFFSIZE 1024*64 // Jeff.add.2014.08.07-------------------------------------------------------- /************************************************************************/ /* Copyright (C), 2016-2020, [IT], 保留所有权利; /* 模 块 名:CSocketHandle类; /* 描 述:套接字通信类; /* /* 版 本:[V]; /* 作 者:[IT]; /* 日 期:[2/29/2016]; /* /* /* 注 意:; /* /* 修改记录:[IT]; /* 修改日期:; /* 修改版本:; /* 修改内容:; /************************************************************************/ class CSocketHandle { public: CSocketHandle(); ~CSocketHandle(); // 套接字是否打开,打开返回TRUE; bool IsOpen() const; // 返回套接字句柄(如果对象关闭,句柄值为INVALID_SOCKET); SOCKET GetSocket() const; // 获取套接字类型(返回-1表示不是一个有效的套接字) int GetSocketType() const; // 附加套接字; bool Attach(IN SOCKET sock); // 从类中分离套接字; SOCKET Detach(); // 获取套接字名(本地地址); bool GetSockName(OUT SockAddrIn& saddr_in) const; // 获取点对点的套接接名(获取Peer地址); bool GetPeerName(OUT SockAddrIn& saddr_in) const; // 关闭套接字; void Close(); // 记录多播地址; bool AddMembership(IN LPCTSTR pszIPAddr, IN LPCTSTR pszNIC); // 移除多播地址; bool DropMembership(IN LPCTSTR pszIPAddr, IN LPCTSTR pszNIC); // 创建服务端套接字; bool CreateSocket(IN LPCTSTR pszHostName, IN LPCTSTR pszServiceName, IN int nFamily, IN int nType, IN UINT uOptions = 0); // 客户端连接服务端; bool ConnectTo(IN LPCTSTR pszHostName, IN LPCTSTR pszRemote, IN LPCTSTR pszServiceName, IN int nFamily, IN int nType); // 从套接字读取内容; DWORD Read(OUT LPBYTE lpBuffer, IN DWORD dwSize, IN LPSOCKADDR lpAddrIn = NULL, IN DWORD dwTimeout = INFINITE); #ifdef WIN32 // 异步从套接字读取内容; DWORD ReadEx(OUT LPBYTE lpBuffer, IN DWORD dwSize, IN LPSOCKADDR lpAddrIn, IN LPWSAOVERLAPPED lpOverlapped, IN LPWSACOMPLETIONROUTINE lpCompletionRoutine); #endif // 向目标套接字发送内容; DWORD Write(IN const LPBYTE lpBuffer, IN DWORD dwCount, IN const LPSOCKADDR lpAddrIn = NULL, IN DWORD dwTimeout = INFINITE); #ifdef WIN32 // 异步向目标套接字发送内容; DWORD WriteEx(IN const LPBYTE lpBuffer, IN DWORD dwCount, IN const LPSOCKADDR lpAddrIn, IN LPWSAOVERLAPPED lpOverlapped, IN LPWSACOMPLETIONROUTINE lpCompletionRoutine); #endif #ifdef WIN32 // Control the mode of a socket (asynchronous mode); bool IOControl( IN DWORD dwIoCode, IN LPBYTE lpInBuffer, IN DWORD cbInBuffer, IN LPBYTE lpOutBuffer, IN DWORD cbOutBuffer, IN LPDWORD lpcbBytesReturned, IN LPWSAOVERLAPPED lpOverlapped, IN LPWSACOMPLETIONROUTINE lpCompletionRoutine ); // Get Overlapped result (asynchronous mode); bool GetTransferOverlappedResult(IN LPWSAOVERLAPPED lpOverlapped, IN LPDWORD lpcbTransfer, IN bool bWait = true, IN LPDWORD lpdwFlags = 0); #endif // Initialize Winsock library. This function calls WSAStartup; static bool InitLibrary(IN WORD wVersion); // Release Winsock library; static bool ReleaseLibrary(); // Wait for a new connection; static SOCKET WaitForConnection(IN SOCKET sock); // Shutdown a connection; static bool ShutdownConnection(IN SOCKET sock); // Check if IP address is unicast (network order); static bool IsUnicastIP( IN ULONG ulAddr ); // Check if IP address is multicast (network order); static bool IsMulticastIP( IN ULONG ulAddr ); // Format IP address to string; static bool FormatIP(LPTSTR pszIPAddr, UINT nSize, ULONG ulAddr, bool bFmtHost); // Format IP address to string; static bool FormatIP(LPTSTR pszIPAddr, UINT nSize, const SockAddrIn& addrIn); // Get service port number; static USHORT GetPortNumber( LPCTSTR pszServiceName ); // Get IP address of a host; static ULONG GetIPAddress( LPCTSTR pszHostName ); // Get current localname for this machine; static bool GetLocalName(LPTSTR pszName, UINT nSize); // Get current (default) IP address for this machine; static bool GetLocalAddress(LPTSTR pszAddress, UINT nSize, int nFamily = AF_INET); // Get IP address info of a host (Supports: IPv4 and IPv6); static bool GetAddressInfo( LPCTSTR pszHostName, LPCTSTR pszServiceName, int nFamily, SockAddrIn& sockAddr); // CSocketHandle - data protected: SOCKET m_hSocket; ///< socket handle // Jeff.add.2014.08.07-----------------------------------. public: unsigned char m_szpendingbuf[SOCKET_BUFFSIZE]; unsigned int m_npendingSize; CRITICAL_SECTION m_hClient2SrvSection; // Jeff.add.2014.08.07-----------------------------------. }; #endif // __SOCKETHANDLE_20160228__