由于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;
}
}