对Windows下的Socket通信进行封装


由于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_SUCC	0
#define NET_SOCKET_FAILE	-1
#define NET_SOCKET_TIMEOUT -11


class CMSSocket  
{
public:
	CMSSocket();
	CMSSocket(int socket);
	virtual ~CMSSocket();
	
	CMSSocket& operator=(const CMSSocket socket);

	void SetSocketExitFlag(bool bExit);
	void SetSocket(int socket);
	int	GetSocket();

	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);	
	   
    //此函数只用于TCP
	int 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);
	//此函数只用于TCP
	int 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:
	bool	m_bExit;
	int		m_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_FILE
static 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;
	WSADATA	wsadata;
	
	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)
	{//启用select
		fd_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) 
		{
			// success
			return 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 case
	
	struct 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;
	}
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值