对Windows下的Socket通信进行封装

来源:互联网 发布:linux 调整时区 编辑:程序博客网 时间:2024/05/20 17:25
由于socket通信的大部分代码都有重合现象。所以针对TCP和UDP数据传输封装了一个类,可以基于此类传输数据。

类如下:

MSSocket.h文件:
// MSSocket.h: interface for the CMSSocket class.////////////////////////////////////////////////////////////////////////#if !defined(AFX_MSSOCKET_H__0418D61F_122D_4840_900D_CD688760E189__INCLUDED_)#define AFX_MSSOCKET_H__0418D61F_122D_4840_900D_CD688760E189__INCLUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000#define  _WINSOCK_DEPRECATED_NO_WARNINGS#define FD_SETSIZE 1024#include <winsock2.h>#include <ws2tcpip.h>#include <assert.h>#pragma comment(lib, "ws2_32.lib")#define MAKE_SOCKADDR_IN(var,adr,prt) \    struct sockaddr_in var;\    var.sin_family = AF_INET;\    var.sin_addr.s_addr = (adr);\    var.sin_port = (prt);\#define NET_SOCKET_SUCC0#define NET_SOCKET_FAILE-1#define NET_SOCKET_TIMEOUT -11class CMSSocket  {public:CMSSocket();CMSSocket(int socket);virtual ~CMSSocket();CMSSocket& operator=(const CMSSocket socket);void SetSocketExitFlag(bool bExit);void SetSocket(int socket);intGetSocket();static int initializeWinsockIfNecessary();static int setupDatagramSocket(SOCKET *sock, const char* szIPAddress=NULL, DWORD dwPort=0/*,bool makeNonBlocking = false*/);static int setupStreamSocket(SOCKET *sock, const char* szIPAddress=NULL, DWORD dwPort=0/*, bool makeNonBlocking = false*/);//使用了非阻塞的connect方式static int connectSocket(SOCKET *sock,const char* szServer, DWORD nPort);int AcceptSocket(SOCKET *sock, struct sockaddr* clientAddr, int* addrlen, bool makeSelect = false, const struct timeval* timeout = NULL);int closeSocket(bool graceful);int listenSocket(int backlog);int readSocket(unsigned int nType,unsigned char* buffer, unsigned int bufferSize,struct sockaddr_in& fromAddress,struct timeval* timeout = NULL);       //此函数只用于TCPint readSocketExact(unsigned char* buffer, unsigned int bufferSize,struct sockaddr_in& fromAddress,struct timeval* timeout = NULL);int writeSocket(unsigned int nType, unsigned char* buffer, unsigned int bufferSize,const char* szDestIP = NULL, DWORD dwDestPort = 0, struct timeval* timeout = NULL);//此函数只用于TCPint writeSocketExact(unsigned char* buffer, unsigned int bufferSize, const char* szDestIP = NULL, DWORD dwDestPort = 0, struct timeval* timeout = NULL);unsigned int getBufferSize(int bufOptName);unsigned int getSendBufferSize();unsigned int getReceiveBufferSize();unsigned int setBufferTo(int bufOptName, unsigned int requestedSize);unsigned int setSendBufferTo( unsigned int requestedSize);unsigned int setReceiveBufferTo( unsigned int requestedSize);unsigned int increaseBufferTo(int bufOptName, unsigned int requestedSize);unsigned int increaseSendBufferTo( unsigned int requestedSize);unsigned int increaseReceiveBufferTo( unsigned int requestedSize);bool makeSocketNonBlocking();bool makeSocketBlocking();bool makeSocketLingerON();bool makeSocketLingerOFF();static bool IsMulticastAddress(unsigned int address /* network address*/);static bool socketJoinGroup(int socket, unsigned int groupAddress, /* network address*/ unsigned int RecvAddress /* network address*/);static bool socketLeaveGroup(int socket, unsigned int groupAddress, /* network address*/unsigned int RecvAddress /* network address*/);private:boolm_bExit;intm_nSocket;};#endif // !defined(AFX_MSSOCKET_H__0418D61F_122D_4840_900D_CD688760E189__INCLUDED_)

MSSocket.cpp文件:
// MSSocket.cpp: implementation of the CMSSocket class.////////////////////////////////////////////////////////////////////////#include "MSSocket.h"#ifdef _DEBUG#undef THIS_FILEstatic char THIS_FILE[]=__FILE__;#define new DEBUG_NEW#endif#include <stdio.h>#pragma warning(disable:4244)//////////////////////////////////////////////////////////////////////// Construction/Destruction//////////////////////////////////////////////////////////////////////CMSSocket::CMSSocket(){m_bExit = false;m_nSocket = INVALID_SOCKET;}CMSSocket::CMSSocket(int socket){m_bExit = false;m_nSocket = socket;}CMSSocket::~CMSSocket(){}CMSSocket& CMSSocket::operator=(const CMSSocket socket){if (this != &socket){this->m_nSocket = socket.m_nSocket;this->m_bExit = socket.m_bExit;}return *this;}void CMSSocket::SetSocket(int socket){m_nSocket = socket;}int CMSSocket::GetSocket(){return m_nSocket;}int CMSSocket::initializeWinsockIfNecessary(){#define WS_VERSION_CHOICE1 0x202/*MAKEWORD(2,2)*/#define WS_VERSION_CHOICE2 0x101/*MAKEWORD(1,1)*/static int _haveInitializedWinsock = 0;WSADATAwsadata;if (!_haveInitializedWinsock){if ((WSAStartup(WS_VERSION_CHOICE1, &wsadata)  != 0) &&   ((WSAStartup(WS_VERSION_CHOICE2, &wsadata)) != 0)) {return NET_SOCKET_FAILE;}if ((wsadata.wVersion != WS_VERSION_CHOICE1) &&(wsadata.wVersion != WS_VERSION_CHOICE2)) {WSACleanup();return NET_SOCKET_FAILE; }_haveInitializedWinsock = 1;}return NET_SOCKET_SUCC;}int CMSSocket::setupDatagramSocket(SOCKET *sock, const char* szIPAddress, DWORD dwPort/*, bool makeNonBlocking*/){assert(sock != NULL);int result = NET_SOCKET_FAILE;__try{if (NET_SOCKET_FAILE == initializeWinsockIfNecessary()){__leave;}*sock = socket(AF_INET, SOCK_DGRAM, 0);if (*sock == INVALID_SOCKET){__leave;}/*int reuseFlag = 1;if (SOCKET_ERROR == setsockopt(*sock, SOL_SOCKET, SO_REUSEADDR,(const char*)&reuseFlag, sizeof reuseFlag)){__leave;}*/unsigned int addr = (szIPAddress == NULL) ? INADDR_ANY : inet_addr(szIPAddress);MAKE_SOCKADDR_IN(name, addr, htons(dwPort));if (0 != bind(*sock, (struct sockaddr*)&name, sizeof name)){__leave;}//if (makeNonBlocking)//{//非阻塞模式//unsigned long arg = 1;//if (ioctlsocket(*sock, FIONBIO, &arg) == SOCKET_ERROR)//{//__leave;//}//}result = NET_SOCKET_SUCC;}__finally{if (NET_SOCKET_FAILE == result && *sock!=INVALID_SOCKET){closesocket(*sock);*sock = INVALID_SOCKET;}}return result;}int CMSSocket::setupStreamSocket(SOCKET *sock, const char* szIPAddress, DWORD dwPort/*, bool makeNonBlocking*/){assert(sock != NULL);int result = NET_SOCKET_FAILE;__try{if (NET_SOCKET_FAILE == initializeWinsockIfNecessary()){__leave;}*sock = socket(AF_INET, SOCK_STREAM, 0);if (*sock == INVALID_SOCKET){__leave;}/*int reuseFlag = 1;if (setsockopt(newSocket, SOL_SOCKET, SO_REUSEADDR,(const char*)&reuseFlag, sizeof reuseFlag) == SOCKET_ERROR){__leave;}*/unsigned int addr = (szIPAddress == NULL) ? INADDR_ANY : inet_addr(szIPAddress);MAKE_SOCKADDR_IN(name, addr, htons(dwPort));if (0 != bind(*sock, (struct sockaddr*)&name, sizeof name)){__leave;}/*if (makeNonBlocking){unsigned long arg = 1;if (ioctlsocket(*sock, FIONBIO, &arg) == SOCKET_ERROR){__leave;}}*/result = NET_SOCKET_SUCC;}__finally{if (NET_SOCKET_FAILE == result && *sock != INVALID_SOCKET){closesocket(*sock);*sock == INVALID_SOCKET;}}return result;}int CMSSocket::connectSocket(SOCKET *sock, const char* szServer, DWORD nPort){assert(sock != NULL);int result = NET_SOCKET_FAILE;__try{*sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (*sock == INVALID_SOCKET){__leave;}unsigned int addr = (szServer == NULL) ? INADDR_ANY : inet_addr(szServer);MAKE_SOCKADDR_IN(serveraddr, addr, htons(nPort));u_long value = 1;ioctlsocket(*sock, FIONBIO, &value);//设置为非阻塞if (SOCKET_ERROR == connect(*sock, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) &&WSAEWOULDBLOCK == WSAGetLastError()){TIMEVAL timeout;timeout.tv_sec = 2;timeout.tv_usec = 0;FD_SET mask;FD_ZERO(&mask);FD_SET(*sock, &mask);value = select(NULL, NULL, &mask, NULL, &timeout);if (value && value != SOCKET_ERROR){//连接成功value = 0;ioctlsocket(*sock, FIONBIO, &value);//设置为阻塞result = NET_SOCKET_SUCC;}}}__finally{if (result == NET_SOCKET_FAILE && *sock!=INVALID_SOCKET){closesocket(*sock);*sock = INVALID_SOCKET;}}return result;}int CMSSocket::AcceptSocket(SOCKET *sock, struct sockaddr* clientAddr, int* addrlen, bool makeSelect, const struct timeval* timeout){assert(sock != NULL);if (makeSelect){//启用selectfd_set readfds;FD_ZERO(&readfds);FD_SET(m_nSocket, &readfds);int result = select(0, &readfds, (fd_set *)0, (fd_set *)0, timeout);if (result == 0)//超时{return NET_SOCKET_TIMEOUT;}else if ((result == SOCKET_ERROR) || (!FD_ISSET(m_nSocket, &readfds))){return NET_SOCKET_FAILE;}}*sock = accept(m_nSocket, clientAddr, addrlen);if (INVALID_SOCKET == *sock){return NET_SOCKET_FAILE;}else{return NET_SOCKET_SUCC;}}int CMSSocket::listenSocket(int backlog){if (SOCKET_ERROR == listen(m_nSocket, backlog)){return NET_SOCKET_FAILE;}else{return NET_SOCKET_SUCC;}}int CMSSocket::closeSocket(bool graceful){if (graceful){shutdown(m_nSocket, SD_BOTH);while (1){char szBuf[1024];int nRet = recv(m_nSocket, szBuf, 1024, 0);if (nRet == 0)//连接优雅关闭{break;}else if (nRet == SOCKET_ERROR)//有错误发生{return NET_SOCKET_FAILE;}Sleep(1);}}if (SOCKET_ERROR == closesocket(m_nSocket)){return NET_SOCKET_FAILE;}else{m_bExit = true;//关闭socket,退出数据接收和发送m_nSocket = INVALID_SOCKET;return NET_SOCKET_SUCC;}}int CMSSocket::readSocket(unsigned int nType, unsigned char* buffer, unsigned int bufferSize,  struct sockaddr_in& fromAddress,struct timeval* timeout){int bytesRead = 0;fd_set fdread;FD_ZERO(&fdread);FD_SET(m_nSocket, &fdread);bytesRead = select(0, &fdread, NULL, NULL, timeout);if (bytesRead == 0)//接收超时{return NET_SOCKET_TIMEOUT;}else if (bytesRead == SOCKET_ERROR)//socket错误{return NET_SOCKET_FAILE;}else if (bytesRead > 0){if (FD_ISSET(m_nSocket, &fdread)){if (nType == 1 /* tcp recv */){bytesRead = recv(m_nSocket, (char*)buffer, bufferSize, 0);}else if (nType == 0)/* udp recv */{int addressSize = sizeof fromAddress;bytesRead = recvfrom(m_nSocket, (char*)buffer, bufferSize, 0,(struct sockaddr*)&fromAddress, &addressSize);}else if (nType == 2) /*multicast*/{bytesRead = recvfrom(m_nSocket, (char*)buffer, bufferSize, 0, NULL, NULL);}}}if (bytesRead <= 0)//对方关闭socket或者socket错误{return NET_SOCKET_FAILE;}return bytesRead;}/*描述:如果返回-1表示socket出错,否则返回接收的数据大小。*/int CMSSocket::readSocketExact(unsigned char* buffer, unsigned int bufferSize,   struct sockaddr_in& fromAddress,struct timeval* timeout){int bsize = bufferSize;int bytesRead = 0;int totBytesRead =0;do {// 该函数只用在TCP模式下bytesRead = readSocket(1/*for tcp*/, buffer + totBytesRead, bsize,fromAddress, timeout);if (bytesRead == NET_SOCKET_FAILE || //sock被关闭或socket错误bytesRead==NET_SOCKET_TIMEOUT)//超时{return bytesRead;}totBytesRead += bytesRead;bsize -= bytesRead;Sleep(1);//防止有数据的时候读的太快导致CPU使用率很高} while (bsize > 0 && !m_bExit);return totBytesRead;}int CMSSocket::writeSocket(unsigned int nType, unsigned char* buffer, unsigned bufferSize, const char* szDestIP, DWORD DestPort, struct timeval* timeout){int iWrite = -1;if (nType == 1 /* tcp send*/){fd_set fdwrite;timeval timeout = { 10, 0 };//超时时长FD_ZERO(&fdwrite);FD_SET(m_nSocket, &fdwrite);iWrite = select(0, NULL, &fdwrite, NULL, &timeout);if (iWrite == 0){return NET_SOCKET_TIMEOUT;}else if (iWrite == SOCKET_ERROR || !FD_ISSET(m_nSocket, &fdwrite)){return NET_SOCKET_FAILE;}else if (iWrite > 0){iWrite = send(m_nSocket, (const char*)buffer, bufferSize, 0);}}else /*udp sedn*/{MAKE_SOCKADDR_IN(name, (inet_addr(szDestIP)), (htons(DestPort)));iWrite = sendto(m_nSocket, (const char*)buffer, bufferSize, 0, (sockaddr*)&name, sizeof name);}if (iWrite == SOCKET_ERROR){return NET_SOCKET_FAILE;}return iWrite;}int CMSSocket::writeSocketExact(unsigned char* buffer, unsigned int bufferSize, const char* szDestIP, DWORD dwDestPort, struct timeval* timeout){int bsize = bufferSize;int bytesWrite = 0;int totBytesWrite = 0;do{// 该函数只用在TCP模式下bytesWrite = writeSocket(1/*for tcp*/, buffer + totBytesWrite, bsize,NULL,0, timeout);if (bytesWrite == NET_SOCKET_FAILE ||bytesWrite == NET_SOCKET_TIMEOUT){return bytesWrite;}totBytesWrite += bytesWrite;bsize -= bytesWrite;} while (bsize > 0 && !m_bExit);return totBytesWrite;}unsigned int CMSSocket::getBufferSize(int bufOptName){unsigned curSize;int sizeSize = sizeof curSize;if (getsockopt(m_nSocket, SOL_SOCKET, bufOptName,(char*)&curSize, &sizeSize) == SOCKET_ERROR){return NET_SOCKET_FAILE;}return curSize;}unsigned int CMSSocket::getSendBufferSize(){return getBufferSize(SO_SNDBUF);}unsigned int CMSSocket::getReceiveBufferSize(){return getBufferSize(SO_RCVBUF);}unsigned int CMSSocket::setBufferTo(int bufOptName, unsigned int requestedSize){int sizeSize = sizeof requestedSize;if (SOCKET_ERROR == setsockopt(m_nSocket, SOL_SOCKET, bufOptName, (char*)&requestedSize, sizeSize)){return NET_SOCKET_FAILE;}// Get and return the actual, resulting buffer size:return getBufferSize(bufOptName);}unsigned int CMSSocket::setSendBufferTo(unsigned int requestedSize){return setBufferTo(SO_SNDBUF, requestedSize);}unsigned int CMSSocket::setReceiveBufferTo( unsigned int requestedSize){return setBufferTo(SO_RCVBUF, requestedSize);}unsigned int CMSSocket::increaseBufferTo(int bufOptName, unsigned int requestedSize){unsigned int curSize = getBufferSize(bufOptName);while (requestedSize > curSize){int sizeSize = sizeof requestedSize;if (setsockopt(m_nSocket, SOL_SOCKET, bufOptName,(char*)&requestedSize, sizeSize) == 0) {// successreturn requestedSize;}requestedSize = (requestedSize + curSize)/2;}return getBufferSize(bufOptName);}unsigned int CMSSocket::increaseSendBufferTo(unsigned int requestedSize){return increaseBufferTo(SO_SNDBUF, requestedSize);}unsigned int CMSSocket::increaseReceiveBufferTo( unsigned int requestedSize){return increaseBufferTo(SO_RCVBUF, requestedSize);}bool CMSSocket::makeSocketNonBlocking(){unsigned long arg = 1;return ioctlsocket(m_nSocket, FIONBIO, &arg) == 0;}bool CMSSocket::makeSocketBlocking(){unsigned long arg = 0;return ioctlsocket(m_nSocket, FIONBIO, &arg) == 0;}bool CMSSocket::makeSocketLingerON(){struct linger linger;linger.l_onoff = 0;linger.l_linger = 0;int nRet = setsockopt(m_nSocket, SOL_SOCKET, SO_LINGER,(const char *)&linger, sizeof(linger));return nRet < 0 ? false : true;}bool CMSSocket::makeSocketLingerOFF(){struct linger linger;linger.l_onoff = 1;linger.l_linger = 0;int nRet = setsockopt(m_nSocket, SOL_SOCKET, SO_LINGER,(const char *)&linger, sizeof(linger));return nRet < 0 ? false : true;}void CMSSocket::SetSocketExitFlag(bool bExit){m_bExit = bExit;}bool CMSSocket::IsMulticastAddress(unsigned int address) {unsigned int addressInHostOrder = ntohl(address);return addressInHostOrder >  0xE00000FF &&addressInHostOrder <= 0xEFFFFFFF;}bool CMSSocket::socketJoinGroup(int socket, unsigned int groupAddress, unsigned int RecvAddress){if (!IsMulticastAddress(groupAddress)) return true; // ignore this casestruct ip_mreq imr;imr.imr_multiaddr.s_addr = groupAddress;imr.imr_interface.s_addr = RecvAddress;if (setsockopt(socket, IPPROTO_IP, IP_ADD_MEMBERSHIP,(const char*)&imr, sizeof (struct ip_mreq)) < 0) {return false;}else{ return true;}}bool CMSSocket::socketLeaveGroup(int socket, unsigned int groupAddress, unsigned int RecvAddress){if (!IsMulticastAddress(groupAddress)) return true; // 忽略这种情况struct ip_mreq imr;imr.imr_multiaddr.s_addr = groupAddress;imr.imr_interface.s_addr = RecvAddress;if (setsockopt(socket, IPPROTO_IP, IP_DROP_MEMBERSHIP,(const char*)&imr, sizeof (struct ip_mreq)) < 0){return false; }else { return true;}}





原创粉丝点击