- Socket.h
- #ifndef __SOCKET_H__
- #define __SOCKET_H__
- #include <winsock2.h>
- #pragma comment(lib, "ws2_32.lib")
- #pragma warning(disable : 4786)
- #include <errno.h>
- #include <vector>
- using namespace std;
- // select mode
- #define SELECT_MODE_READY 0x001
- #define SELECT_MODE_WRITE 0x002
- // select return codes
- #define SELECT_STATE_READY 0
- #define SELECT_STATE_ERROR 1
- #define SELECT_STATE_ABORTED 2
- #define SELECT_STATE_TIMEOUT 3
- class Socket
- {
- public:
- Socket(UINT mtu = 1500);
- virtual ~Socket();
- virtual void Close();
- virtual int Write(PBYTE pBuffer, int writeSize, UINT nTimeOut = 500000); // 0.5sec
- virtual int Read(BYTE* pBuffer, int readSize, UINT nTimeOut = 500000); // 0.5sec
- virtual SOCKADDR_IN GetBindAddr();
- virtual SOCKADDR_IN GetConnectAddr();
- virtual UINT GetMTU();
- static BOOL GetLocalIPList(vector<string>& vIPList);
- static BOOL GetAdapterSpeed(vector<int>& vList);
- protected:
- void ReportError();
- int Select(int mode, int timeoutUsec);
- BOOL m_isOpen;
- SOCKET m_Socket;
- SOCKADDR_IN m_BindAddr;
- SOCKADDR_IN m_ConnectAddr;
- UINT m_Mtu;
- };
- #endif //__SOCKET_H__
Socket.cpp
- #include "stdafx.h"
- #include "Socket.h"
- Socket::Socket(UINT mtu)
- :m_Mtu(mtu)
- {
- WSADATA wsaData;
- WORD wVersionRequested = MAKEWORD( 2, 2 );
- WSAStartup(wVersionRequested, &wsaData);
- m_Socket = NULL;
- memset(&m_BindAddr, 0, sizeof(m_BindAddr));
- memset(&m_ConnectAddr, 0, sizeof(m_ConnectAddr));
- m_isOpen = FALSE;
- }
- Socket::~Socket()
- {
- Close();
- WSACleanup();
- }
- void Socket::Close()
- {
- if (m_Socket)
- closesocket(m_Socket);
- m_Socket = NULL;
- m_isOpen = FALSE;
- }
- int Socket::Read(BYTE* pBuffer, int readSize, UINT nTimeOut)
- {
- int selectState;
- int recvSize;
- if (!pBuffer || !m_isOpen)
- return -1;
- selectState = Select(SELECT_MODE_READY, nTimeOut);
- if (SELECT_STATE_TIMEOUT == selectState)
- return 0;
- if (SELECT_STATE_READY == selectState)
- {
- recvSize = recv(m_Socket, (char*)pBuffer, readSize, 0);
- if (recvSize <= 0)
- return -1;
- return recvSize;
- }
- return -1;
- }
- int Socket::Write(PBYTE pBuffer, int writeSize, UINT nTimeOut)
- {
- int selectState = 0;
- int sendSize = 0;
- if (!pBuffer || !m_isOpen)
- return -1;
- selectState = Select(SELECT_MODE_WRITE, nTimeOut);
- if (selectState == SELECT_STATE_TIMEOUT)
- return 0;
- if (selectState == SELECT_STATE_READY)
- {
- sendSize = send(m_Socket, (char*)pBuffer, writeSize, 0);
- if (sendSize <= 0)
- return -1;
- return sendSize;
- }
- return -1;
- }
- SOCKADDR_IN Socket::GetBindAddr()
- {
- return m_BindAddr;
- }
- SOCKADDR_IN Socket::GetConnectAddr()
- {
- return m_ConnectAddr;
- }
- UINT Socket::GetMTU()
- {
- return m_Mtu;
- }
- // Waits for a file descriptor/socket to change status.
- //
- // network input plugins should use this function in order to
- // not freeze the engine.
- //
- // params :
- // mode SELECT_MODE_READY, SELECT_MODE_WRITE
- // timeout_usec timeout in microsecond
- //
- // return value :
- // SELECT_STATE_READY the file descriptor is ready for cmd
- // SELECT_STATE_ERROR an i/o error occured
- // SELECT_STATE_ABORTED command aborted by an other thread
- // SELECT_STATE_TIMEOUT the file descriptor is not ready after timeout_usec microsecond
- int Socket::Select(int mode, int timeoutUsec)
- {
- fd_set fdset;
- fd_set *readSet, *writeSet;
- timeval selectTimeout;
- int ret;
- selectTimeout.tv_sec = 0;
- selectTimeout.tv_usec = timeoutUsec;
- FD_ZERO (&fdset);
- FD_SET (m_Socket, &fdset);
- readSet = (mode & SELECT_MODE_READY) ? &fdset : NULL;
- writeSet = (mode & SELECT_MODE_WRITE) ? &fdset : NULL;
- ret = select ( (int)m_Socket + 1, readSet, writeSet, NULL, &selectTimeout);
- if (ret == 1)
- return SELECT_STATE_READY;
- if (ret == SOCKET_ERROR)
- {
- if ( errno == EINTR)
- return SELECT_STATE_ABORTED;
- ReportError();
- return SELECT_STATE_ERROR;
- }
- return SELECT_STATE_TIMEOUT;
- }
- void Socket::ReportError()
- {
- int isErr = WSAGetLastError();
- printf("Socket error is:%d\n", isErr);
- //Close();
- }
- BOOL Socket::GetLocalIPList(vector<string>& vIPList)
- {
- WORD wVersionRequested;
- WSADATA wsaData;
- int err;
- wVersionRequested = MAKEWORD( 2, 2 );
- err = WSAStartup( wVersionRequested, &wsaData );
- if ( err != 0 )
- {
- printf("GetLocalIPList : WSAStartup failed !");
- return FALSE;
- }
- char szhn[256];
- int nStatus = gethostname(szhn, sizeof(szhn));
- if (nStatus == SOCKET_ERROR )
- {
- printf("Socket : Gethostname failed, Error code: %d", WSAGetLastError());
- return FALSE;
- }
- HOSTENT *host = gethostbyname(szhn);
- if (host != NULL)
- {
- for ( int i=0; ; i++ )
- {
- vIPList.push_back( inet_ntoa( *(IN_ADDR*)host->h_addr_list[i] ) ) ;
- if ( host->h_addr_list[i] + host->h_length >= host->h_name )
- break;
- }
- }
- WSACleanup();
- return TRUE;
- }
Udp.h
- #ifndef __UDP_H__
- #define __UDP_H__
- #include "Socket.h"
- #include <WS2tcpip.h>
- #include <string>
- using namespace std;
- class Udp : public Socket
- {
- public:
- Udp(UINT mtu = 1500);
- virtual ~Udp();
- virtual BOOL Open(string bindIp = "", int bindPort = 0);
- virtual BOOL Connect(string connectIp, int connectPort);
- virtual int Read(BYTE* pBuffer, UINT16 bufferSize, UINT nTimeOut = 500000);
- virtual int Write(PBYTE pBuffer, UINT16 bufferSize, UINT nTimeOut = 500000);
- protected:
- BOOL SetMulticast(PCSTR textIP);
- BOOL m_isConnect;
- };
- #endif //__UDP_H__
- #include "stdafx.h"
- #include "Udp.h"
- Udp::Udp(UINT mtu) :Socket(mtu)
- {
- m_isConnect = FALSE;
- }
- Udp::~Udp()
- {
- }
- BOOL Udp::Open(string bindIp, int bindPort)
- {
- if (m_isOpen)
- return FALSE;
- m_isOpen = FALSE;
- m_isConnect = FALSE;
- int error = 0;
- int i_val = 0;
- if (m_Socket)
- closesocket(m_Socket);
- m_Socket= socket(AF_INET, SOCK_DGRAM, 0);
- if ( m_Socket == INVALID_SOCKET )
- {
- ReportError();
- return FALSE;
- }
- i_val = 0; // 非阻塞方式
- error = ioctlsocket(m_Socket, FIONBIO, (ULONG*)&i_val);
- if (error == SOCKET_ERROR)
- {
- ReportError();
- return FALSE;
- }
- i_val = (int)(1024 * 1024 * 1.25);//2M Byte 1000Mbps的network在0.01秒内最高可以接收到1.25MB数据
- error = setsockopt( m_Socket, SOL_SOCKET, SO_RCVBUF, (char*)&i_val, sizeof(i_val) );
- if (error == SOCKET_ERROR)
- {
- ReportError();
- return FALSE;
- }
- error = setsockopt( m_Socket, SOL_SOCKET, SO_SNDBUF, (char*)&i_val, sizeof(i_val) );
- if (error == SOCKET_ERROR)
- {
- ReportError();
- return FALSE;
- }
- // 可重用
- i_val = 1;
- error = setsockopt(m_Socket, SOL_SOCKET, SO_REUSEADDR, (char*)&i_val, sizeof(i_val));
- if (error == SOCKET_ERROR)
- {
- ReportError();
- return FALSE;
- }
- // 设置ttl
- i_val = 5;
- error = setsockopt(m_Socket,IPPROTO_IP,IP_MULTICAST_TTL,(char*)&i_val, sizeof(i_val));
- if (error == SOCKET_ERROR)
- {
- ReportError();
- return FALSE;
- }
- // 绑定套接字
- memset((PVOID)&m_BindAddr, 0, sizeof(m_BindAddr));
- m_BindAddr.sin_family = AF_INET;
- m_BindAddr.sin_port = htons(bindPort);
- m_BindAddr.sin_addr.s_addr = inet_addr(bindIp.c_str());
- if ( IN_MULTICAST(ntohl(m_BindAddr.sin_addr.s_addr)) || m_BindAddr.sin_addr.s_addr == INADDR_BROADCAST )
- m_BindAddr.sin_addr.s_addr = htonl(INADDR_ANY);
- error = bind(m_Socket, (SOCKADDR*)&m_BindAddr, sizeof(m_BindAddr));
- if (error == SOCKET_ERROR)
- {
- ReportError();
- return FALSE;
- }
- i_val = sizeof(m_BindAddr);
- error = getsockname(m_Socket, (SOCKADDR*)&m_BindAddr, &i_val);
- if (error == SOCKET_ERROR)
- {
- ReportError();
- return FALSE;
- }
- if ( ! SetMulticast(bindIp.c_str()))
- return FALSE;
- m_isOpen = TRUE;
- return TRUE;
- }
- BOOL Udp::Connect(string connectIp, int connectPort)
- {
- if (!m_isOpen)
- return FALSE;
- int error = 0;
- int i_val = 0;
- memset((PVOID)&m_ConnectAddr, 0, sizeof(m_ConnectAddr));
- if ( ! SetMulticast(connectIp.c_str()))
- return FALSE;
- m_ConnectAddr.sin_family = AF_INET;
- m_ConnectAddr.sin_port = htons(connectPort);
- m_ConnectAddr.sin_addr.s_addr = inet_addr(connectIp.c_str());
- if (connect(m_Socket, (SOCKADDR*)&m_ConnectAddr, sizeof(m_ConnectAddr)) == SOCKET_ERROR )
- {
- ReportError();
- return FALSE;
- }
- m_isConnect = TRUE;
- return TRUE;
- }
- int Udp::Read(BYTE* pBuffer, UINT16 bufferSize, UINT nTimeOut)
- {
- int iRead;
- if ( !m_isOpen )
- return -1;
- iRead = Socket::Read(pBuffer, bufferSize, nTimeOut);
- return iRead;
- }
- int Udp::Write(PBYTE pBuffer, UINT16 bufferSize, UINT nTimeOut)
- {
- int iWrite;
- if ( !m_isOpen || !m_isConnect)
- return -1;
- iWrite = Socket::Write(pBuffer, bufferSize, nTimeOut);
- return iWrite;
- }
- BOOL Udp::SetMulticast(PCSTR textIP)
- {
- int error = 0;
- int i_val = 0;
- // 设置多播和广播
- if ( IN_MULTICAST(ntohl(inet_addr(textIP))) )
- {
- i_val = 1;
- error = setsockopt(m_Socket, IPPROTO_IP, IP_MULTICAST_LOOP, (char*)&i_val, sizeof(i_val) );
- if (error == SOCKET_ERROR)
- {
- ReportError();
- return FALSE;
- }
- ip_mreq multicastAddr;
- multicastAddr.imr_multiaddr.s_addr = inet_addr(textIP);
- multicastAddr.imr_interface.s_addr = htonl(INADDR_ANY);
- error = setsockopt(m_Socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&multicastAddr, sizeof(multicastAddr));
- if (error == SOCKET_ERROR)
- {
- ReportError();
- return FALSE;
- }
- }
- //设置广播
- if ( inet_addr(textIP) == INADDR_BROADCAST )
- {
- i_val = 1;
- error = setsockopt( m_Socket, SOL_SOCKET, SO_BROADCAST, (char*)&i_val, sizeof(i_val) );
- if (error == SOCKET_ERROR)
- {
- ReportError();
- return FALSE;
- }
- }
- return TRUE;
- }