Win32 SOCKET之UDP

来源:互联网 发布:北津学院教务网络 编辑:程序博客网 时间:2024/06/06 05:39
  1. Socket.h  
[cpp] view plain copy
  1. #ifndef __SOCKET_H__  
  2. #define __SOCKET_H__  
  3.   
  4. #include <winsock2.h>  
  5. #pragma comment(lib, "ws2_32.lib")  
  6.   
  7. #pragma warning(disable : 4786)   
  8.   
  9. #include <errno.h>  
  10. #include <vector>  
  11. using namespace std;  
  12.   
  13. // select mode   
  14. #define SELECT_MODE_READY   0x001  
  15. #define SELECT_MODE_WRITE   0x002  
  16.   
  17. // select return codes   
  18. #define SELECT_STATE_READY         0  
  19. #define SELECT_STATE_ERROR         1  
  20. #define SELECT_STATE_ABORTED       2  
  21. #define SELECT_STATE_TIMEOUT       3  
  22.   
  23. class Socket  
  24. {  
  25. public:  
  26.     Socket(UINT mtu = 1500);  
  27.     virtual ~Socket();  
  28.   
  29.     virtual void Close();  
  30.   
  31.     virtual int Write(PBYTE pBuffer, int writeSize, UINT nTimeOut = 500000);  // 0.5sec  
  32.     virtual int Read(BYTE* pBuffer, int readSize, UINT nTimeOut = 500000); // 0.5sec  
  33.   
  34.     virtual SOCKADDR_IN GetBindAddr();  
  35.     virtual SOCKADDR_IN GetConnectAddr();  
  36.   
  37.     virtual UINT GetMTU();  
  38.   
  39.     static BOOL GetLocalIPList(vector<string>& vIPList);  
  40.     static BOOL GetAdapterSpeed(vector<int>& vList);  
  41.   
  42. protected:  
  43.     void    ReportError();  
  44.     int     Select(int mode, int timeoutUsec);  
  45.   
  46.     BOOL    m_isOpen;  
  47.   
  48.     SOCKET      m_Socket;  
  49.     SOCKADDR_IN m_BindAddr;  
  50.     SOCKADDR_IN m_ConnectAddr;  
  51.   
  52.     UINT    m_Mtu;  
  53. };  
  54.   
  55. #endif //__SOCKET_H__  


Socket.cpp

[cpp] view plain copy
  1. #include "stdafx.h"  
  2. #include "Socket.h"  
  3.   
  4. Socket::Socket(UINT mtu)  
  5. :m_Mtu(mtu)  
  6. {  
  7.     WSADATA wsaData;  
  8.     WORD wVersionRequested = MAKEWORD( 2, 2 );  
  9.     WSAStartup(wVersionRequested, &wsaData);  
  10.   
  11.     m_Socket = NULL;  
  12.     memset(&m_BindAddr, 0, sizeof(m_BindAddr));  
  13.     memset(&m_ConnectAddr, 0, sizeof(m_ConnectAddr));  
  14.   
  15.     m_isOpen = FALSE;  
  16. }  
  17.   
  18. Socket::~Socket()  
  19. {  
  20.     Close();  
  21.   
  22.     WSACleanup();  
  23. }  
  24.   
  25. void Socket::Close()  
  26. {  
  27.     if (m_Socket)  
  28.         closesocket(m_Socket);  
  29.     m_Socket = NULL;  
  30.   
  31.     m_isOpen = FALSE;  
  32. }  
  33.   
  34. int Socket::Read(BYTE* pBuffer, int readSize, UINT nTimeOut)  
  35. {  
  36.     int selectState;  
  37.     int recvSize;  
  38.   
  39.     if (!pBuffer || !m_isOpen)  
  40.         return -1;  
  41.   
  42.     selectState = Select(SELECT_MODE_READY, nTimeOut);  
  43.     if (SELECT_STATE_TIMEOUT == selectState)  
  44.          return 0;  
  45.     if (SELECT_STATE_READY == selectState)  
  46.     {  
  47.         recvSize = recv(m_Socket, (char*)pBuffer, readSize, 0);  
  48.         if (recvSize <= 0)  
  49.             return -1;  
  50.         return recvSize;  
  51.     }  
  52.     return -1;  
  53. }  
  54.   
  55. int Socket::Write(PBYTE pBuffer, int writeSize, UINT nTimeOut)  
  56. {  
  57.     int selectState = 0;  
  58.     int sendSize = 0;  
  59.   
  60.     if (!pBuffer || !m_isOpen)  
  61.         return -1;  
  62.   
  63.     selectState = Select(SELECT_MODE_WRITE, nTimeOut);  
  64.     if (selectState == SELECT_STATE_TIMEOUT)  
  65.         return 0;  
  66.   
  67.     if (selectState == SELECT_STATE_READY)  
  68.     {  
  69.         sendSize = send(m_Socket, (char*)pBuffer, writeSize, 0);  
  70.         if (sendSize <= 0)  
  71.             return -1;  
  72.         return sendSize;  
  73.     }     
  74.   
  75.     return -1;  
  76. }  
  77.   
  78. SOCKADDR_IN Socket::GetBindAddr()  
  79. {  
  80.     return m_BindAddr;  
  81. }  
  82.   
  83. SOCKADDR_IN Socket::GetConnectAddr()  
  84. {  
  85.     return m_ConnectAddr;  
  86. }  
  87.   
  88. UINT Socket::GetMTU()  
  89. {  
  90.     return m_Mtu;  
  91. }  
  92.   
  93.   
  94. //  Waits for a file descriptor/socket to change status.  
  95. //   
  96. //  network input plugins should use this function in order to  
  97. //  not freeze the engine.  
  98. //   
  99. //  params :  
  100. //    mode           SELECT_MODE_READY, SELECT_MODE_WRITE  
  101. //    timeout_usec   timeout in microsecond  
  102. //   
  103. //  return value :  
  104. //    SELECT_STATE_READY     the file descriptor is ready for cmd  
  105. //    SELECT_STATE_ERROR     an i/o error occured  
  106. //    SELECT_STATE_ABORTED   command aborted by an other thread  
  107. //    SELECT_STATE_TIMEOUT   the file descriptor is not ready after timeout_usec microsecond  
  108.   
  109. int Socket::Select(int mode, int timeoutUsec)   
  110. {  
  111.     fd_set fdset;  
  112.     fd_set *readSet, *writeSet;  
  113.     timeval selectTimeout;  
  114.     int ret;  
  115.   
  116.     selectTimeout.tv_sec  = 0;  
  117.     selectTimeout.tv_usec = timeoutUsec;  
  118.   
  119.     FD_ZERO (&fdset);  
  120.     FD_SET  (m_Socket, &fdset);  
  121.   
  122.     readSet = (mode & SELECT_MODE_READY) ? &fdset : NULL;  
  123.     writeSet = (mode & SELECT_MODE_WRITE) ? &fdset : NULL;  
  124.   
  125.     ret = select ( (int)m_Socket + 1, readSet, writeSet, NULL, &selectTimeout);  
  126.   
  127.     if (ret == 1)   
  128.         return SELECT_STATE_READY;  
  129.   
  130.     if (ret == SOCKET_ERROR)   
  131.     {  
  132.         if ( errno == EINTR)  
  133.             return SELECT_STATE_ABORTED;  
  134.   
  135.         ReportError();  
  136.         return SELECT_STATE_ERROR;  
  137.     }   
  138.   
  139.     return SELECT_STATE_TIMEOUT;  
  140. }  
  141.   
  142. void Socket::ReportError()  
  143. {  
  144.     int isErr = WSAGetLastError();  
  145.     printf("Socket error is:%d\n", isErr);  
  146.   
  147.     //Close();  
  148. }  
  149.   
  150. BOOL Socket::GetLocalIPList(vector<string>& vIPList)  
  151. {   
  152.     WORD wVersionRequested;   
  153.     WSADATA wsaData;   
  154.     int err;   
  155.       
  156.     wVersionRequested = MAKEWORD( 2, 2 );   
  157.     err = WSAStartup( wVersionRequested, &wsaData );   
  158.     if ( err != 0 )   
  159.     {  
  160.         printf("GetLocalIPList  : WSAStartup failed !");   
  161.         return FALSE;   
  162.     }   
  163.   
  164.     char szhn[256];   
  165.     int nStatus = gethostname(szhn, sizeof(szhn));   
  166.     if (nStatus == SOCKET_ERROR )   
  167.     {   
  168.         printf("Socket  : Gethostname failed, Error code: %d", WSAGetLastError());   
  169.         return FALSE;   
  170.     }   
  171.       
  172.     HOSTENT *host = gethostbyname(szhn);   
  173.     if (host != NULL)   
  174.     {   
  175.         for ( int i=0; ; i++ )   
  176.         {   
  177.             vIPList.push_back( inet_ntoa( *(IN_ADDR*)host->h_addr_list[i] ) ) ;   
  178.             if ( host->h_addr_list[i] + host->h_length >= host->h_name )   
  179.                 break;   
  180.         }  
  181.     }  
  182.           
  183.     WSACleanup();   
  184.   
  185.     return TRUE;   
  186. }  

Udp.h

[cpp] view plain copy
  1. #ifndef __UDP_H__  
  2. #define __UDP_H__  
  3.   
  4. #include "Socket.h"  
  5. #include <WS2tcpip.h>  
  6.   
  7. #include <string>  
  8. using namespace std;  
  9.   
  10. class Udp : public Socket  
  11. {  
  12. public:  
  13.   
  14.     Udp(UINT mtu = 1500);  
  15.     virtual ~Udp();  
  16.   
  17.     virtual BOOL Open(string bindIp = ""int bindPort = 0);  
  18.   
  19.     virtual BOOL Connect(string connectIp, int connectPort);  
  20.   
  21.     virtual int  Read(BYTE* pBuffer, UINT16 bufferSize, UINT nTimeOut = 500000);  
  22.   
  23.     virtual int  Write(PBYTE pBuffer, UINT16 bufferSize, UINT nTimeOut = 500000);  
  24.   
  25. protected:  
  26.   
  27.     BOOL SetMulticast(PCSTR textIP);  
  28.   
  29.     BOOL    m_isConnect;  
  30. };  
  31.   
  32. #endif //__UDP_H__  


Udp.cpp

[html] view plain copy
  1. #include "stdafx.h"  
  2.   
  3. #include "Udp.h"  
  4.   
  5. Udp::Udp(UINT mtu) :Socket(mtu)  
  6. {  
  7.     m_isConnect = FALSE;  
  8. }  
  9.   
  10. Udp::~Udp()  
  11. {  
  12. }  
  13.   
  14. BOOL Udp::Open(string bindIp, int bindPort)  
  15. {  
  16.     if (m_isOpen)  
  17.         return FALSE;  
  18.   
  19.     m_isOpen = FALSE;  
  20.     m_isConnect = FALSE;  
  21.   
  22.     int error = 0;  
  23.     int i_val = 0;  
  24.       
  25.     if (m_Socket)  
  26.         closesocket(m_Socket);  
  27.     m_Socketsocket(AF_INET, SOCK_DGRAM, 0);  
  28.     if ( m_Socket == INVALID_SOCKET )  
  29.     {  
  30.         ReportError();  
  31.         return FALSE;  
  32.     }  
  33.   
  34.     i_val = 0;  // 非阻塞方式  
  35.     error = ioctlsocket(m_Socket, FIONBIO, (ULONG*)&i_val);  
  36.     if (error == SOCKET_ERROR)  
  37.     {  
  38.         ReportError();  
  39.         return FALSE;  
  40.     }  
  41.   
  42.     i_val = (int)(1024 * 1024 * 1.25);//2M Byte 1000Mbps的network在0.01秒内最高可以接收到1.25MB数据  
  43.     error = setsockopt( m_Socket, SOL_SOCKET, SO_RCVBUF, (char*)&i_val, sizeof(i_val) );  
  44.     if (error == SOCKET_ERROR)  
  45.     {  
  46.         ReportError();  
  47.         return FALSE;  
  48.     }  
  49.   
  50.     error = setsockopt( m_Socket, SOL_SOCKET, SO_SNDBUF, (char*)&i_val, sizeof(i_val) );  
  51.     if (error == SOCKET_ERROR)  
  52.     {  
  53.         ReportError();  
  54.         return FALSE;  
  55.     }     
  56.   
  57.     // 可重用  
  58.     i_val = 1;  
  59.     error = setsockopt(m_Socket, SOL_SOCKET, SO_REUSEADDR, (char*)&i_val, sizeof(i_val));  
  60.     if (error == SOCKET_ERROR)  
  61.     {  
  62.         ReportError();  
  63.         return FALSE;  
  64.     }  
  65.   
  66.     // 设置ttl  
  67.     i_val = 5;  
  68.     error = setsockopt(m_Socket,IPPROTO_IP,IP_MULTICAST_TTL,(char*)&i_val, sizeof(i_val));  
  69.     if (error == SOCKET_ERROR)  
  70.     {  
  71.         ReportError();  
  72.         return FALSE;  
  73.     }  
  74.       
  75.     // 绑定套接字  
  76.     memset((PVOID)&m_BindAddr, 0, sizeof(m_BindAddr));  
  77.   
  78.     m_BindAddr.sin_family = AF_INET;     
  79.     m_BindAddr.sin_port = htons(bindPort);  
  80.     m_BindAddr.sin_addr.s_addr = inet_addr(bindIp.c_str());  
  81.       
  82.     if ( IN_MULTICAST(ntohl(m_BindAddr.sin_addr.s_addr))  || m_BindAddr.sin_addr.s_addr == INADDR_BROADCAST )  
  83.         m_BindAddr.sin_addr.s_addr = htonl(INADDR_ANY);  
  84.       
  85.     error = bind(m_Socket, (SOCKADDR*)&m_BindAddr, sizeof(m_BindAddr));  
  86.     if (error == SOCKET_ERROR)  
  87.     {  
  88.         ReportError();  
  89.         return FALSE;  
  90.     }  
  91.       
  92.     i_val = sizeof(m_BindAddr);  
  93.     error = getsockname(m_Socket, (SOCKADDR*)&m_BindAddr, &i_val);  
  94.     if (error == SOCKET_ERROR)  
  95.     {  
  96.         ReportError();  
  97.         return FALSE;  
  98.     }  
  99.   
  100.     if ( ! SetMulticast(bindIp.c_str()))  
  101.         return FALSE;  
  102.   
  103.     m_isOpen = TRUE;  
  104.     return TRUE;  
  105. }  
  106.   
  107. BOOL Udp::Connect(string connectIp, int connectPort)  
  108. {  
  109.     if (!m_isOpen)  
  110.         return FALSE;  
  111.   
  112.     int error = 0;  
  113.     int i_val = 0;  
  114.   
  115.     memset((PVOID)&m_ConnectAddr, 0, sizeof(m_ConnectAddr));  
  116.   
  117.     if ( ! SetMulticast(connectIp.c_str()))  
  118.         return FALSE;  
  119.   
  120.     m_ConnectAddr.sin_family = AF_INET;  
  121.     m_ConnectAddr.sin_port = htons(connectPort);  
  122.     m_ConnectAddr.sin_addr.s_addr = inet_addr(connectIp.c_str());  
  123.   
  124.     if (connect(m_Socket, (SOCKADDR*)&m_ConnectAddr, sizeof(m_ConnectAddr)) == SOCKET_ERROR )  
  125.     {  
  126.         ReportError();  
  127.         return FALSE;  
  128.     }  
  129.     m_isConnect = TRUE;  
  130.     return TRUE;  
  131. }  
  132.   
  133. int Udp::Read(BYTE* pBuffer, UINT16 bufferSize, UINT nTimeOut)  
  134. {  
  135.     int iRead;  
  136.   
  137.     if ( !m_isOpen )  
  138.         return -1;  
  139.       
  140.     iRead = Socket::Read(pBuffer, bufferSize, nTimeOut);  
  141.   
  142.     return iRead;  
  143. }  
  144.   
  145. int Udp::Write(PBYTE pBuffer, UINT16 bufferSize, UINT nTimeOut)  
  146. {  
  147.     int iWrite;  
  148.   
  149.     if ( !m_isOpen || !m_isConnect)  
  150.         return -1;  
  151.   
  152.     iWrite = Socket::Write(pBuffer, bufferSize, nTimeOut);  
  153.   
  154.     return iWrite;  
  155. }  
  156.   
  157.   
  158. BOOL Udp::SetMulticast(PCSTR textIP)  
  159. {  
  160.     int error = 0;  
  161.     int i_val = 0;  
  162.   
  163.     // 设置多播和广播  
  164.     if ( IN_MULTICAST(ntohl(inet_addr(textIP))) )  
  165.     {  
  166.         i_val = 1;  
  167.         error =  setsockopt(m_Socket, IPPROTO_IP, IP_MULTICAST_LOOP, (char*)&i_val, sizeof(i_val) );  
  168.         if (error == SOCKET_ERROR)  
  169.         {  
  170.             ReportError();  
  171.             return FALSE;  
  172.         }  
  173.           
  174.         ip_mreq multicastAddr;  
  175.         multicastAddr.imr_multiaddr.s_addr = inet_addr(textIP);  
  176.         multicastAddr.imr_interface.s_addr = htonl(INADDR_ANY);  
  177.           
  178.         error = setsockopt(m_Socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&multicastAddr, sizeof(multicastAddr));  
  179.         if (error == SOCKET_ERROR)  
  180.         {  
  181.             ReportError();  
  182.             return FALSE;  
  183.         }  
  184.     }  
  185.       
  186.     //设置广播  
  187.     if ( inet_addr(textIP) == INADDR_BROADCAST )  
  188.     {  
  189.         i_val = 1;  
  190.         error = setsockopt( m_Socket, SOL_SOCKET, SO_BROADCAST, (char*)&i_val, sizeof(i_val) );  
  191.         if (error == SOCKET_ERROR)  
  192.         {  
  193.             ReportError();  
  194.             return FALSE;  
  195.         }  
  196.     }  
  197.     return TRUE;  
  198. }  
原创粉丝点击