Win32 SOCKET之UDP

来源:互联网 发布:用eclipse写java 编辑:程序博客网 时间:2024/05/22 23:28
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_WRITE0x002// select return codes #define SELECT_STATE_READY         0#define SELECT_STATE_ERROR         1#define SELECT_STATE_ABORTED       2#define SELECT_STATE_TIMEOUT       3class Socket{public:Socket(UINT mtu = 1500);virtual ~Socket();virtual void Close();virtual int Write(PBYTE pBuffer, int writeSize, UINT nTimeOut = 500000);  // 0.5secvirtual int Read(BYTE* pBuffer, int readSize, UINT nTimeOut = 500000); // 0.5secvirtual SOCKADDR_IN GetBindAddr();virtual SOCKADDR_IN GetConnectAddr();virtualUINT GetMTU();static BOOL GetLocalIPList(vector<string>& vIPList);static BOOL GetAdapterSpeed(vector<int>& vList);protected:voidReportError();intSelect(int mode, int timeoutUsec);BOOLm_isOpen;SOCKETm_Socket;SOCKADDR_IN m_BindAddr;SOCKADDR_IN m_ConnectAddr;UINTm_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 microsecondint 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);BOOLm_isConnect;};#endif //__UDP_H__


Udp.cpp

#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;}// 设置ttli_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;}
main.cpp#include "Udp.h"#include <process.h>#include <iostream>UINT CALLBACK RecvData(LPVOID arg){Udp recv;if(FALSE == recv.Open("192.168.1.10",2017)){std::cout << "Can not open Udp" << std::endl;return 0;}char dataBuf[100];while(1){memset(dataBuf,'\0',100);PBYTE pTemp = (PBYTE)dataBuf;int nLen = sizeof(dataBuf);int nRead = -1;while(nLen > 0){nRead = recv.Read(pTemp,nLen,1000000);if(nRead == SOCKET_ERROR || nRead == 0) break;pTemp += nRead;nLen  -= nRead;}if(nLen == 0){//std::cout << "GetData: " << dataBuf << std::endl;}}return 0;}int main(){UINT tid;HANDLE hThread = (HANDLE)_beginthreadex(NULL,0,RecvData,NULL,0,&tid);Udp send;send.Open();if(FALSE == send.Connect("192.168.1.10",2017))std::cout << "Can not connect Udp" << std::endl;char* dataBuf = "abcdefghijklmnopqrstuvwxyz";PBYTE pTemp = (PBYTE)dataBuf;int nLen = strlen(dataBuf);int nWrite = -1;while(nLen > 0){nWrite = send.Write(pTemp,nLen);if(nWrite == SOCKET_ERROR || nWrite == 0) break;pTemp += nWrite;nLen  -= nWrite;}system("pause");CloseHandle(hThread);return 0;}


 
原创粉丝点击