www.pudn.com > 2003090514065121890.zip > spIPCComm.h


#ifndef _SP_COMM_H_ 
#define _SP_COMM_H_ 
 
 
/* 
通讯类,by wenyy 2002-02-01 
封装了通信类的读写操作,(类不是线程安全的) 
v.01 支持Socket 
v.02 支持NamedPipe 
通信类中主要封装了通信读写操作 
所有类功能的说明见CIPCComm定义 
v.01 socket communication 
 
2002-06-25 
by wenyy 
将文件编译成为DLL 形式,同时引出相关的全局函数,但建议使用相关类中的静态成员函数 
添加UDP支持 
添加两个新类:CTCPSocket,CUDPSocket,分别支持TCP和UDP协议 
由于UDP包的最大限制关系所以在发送UDP包时需要检测包的最大尺寸 
*/ 
#include  
 
namespace commIPC 
 
//定义错误类型 
//成功 
#define SP_ERR_SUCCESS			0 
//网络错误 
#define SP_ERR_NETWORK			1 
//没有完成读或写,只读入或写出部分要求要求数据 
#define SP_ERR_NOT_FINISH		2 
//超过时间 未使用,被 SP_ERR_NODATA 代替 
#define SP_ERR_TIMEOUT			3 
//无数据 
#define SP_ERR_NODATA			4 
//UDP包长度超过系统限制 
#define SP_UDP_TOOLONG			5 
//UDP接收时缓冲区长度太小 
#define SP_UDP_SMALLBUF			6 
//未实现该调用 
#define SP_ERR_NOT_IMPLEMENT	98 
//一般错误 
#define SP_ERR_GENERAL			99 
 
{//定义名字空间 
 
//pszLocalAddr为本地所使用的IP地址,如果为NULL,表明使用任意IP地址,系统自动选择 
//pszLocalAddr需要绑定的本地地址,如果为NULL表明所有地址 
//返回INVALID_SOCKET表明失败 
extern "C" SOCKET SPCreateListenSocket(LPCSTR pszLocalAddr,UINT uPort); 
//创建客户端SOCKET 
//pszLocalAddr需要绑定的本地地址,如果为NULL表明所有地址 
//返回INVALID_SOCKET表明失败 
extern "C" SOCKET SPCreateConnectSocket(LPCSTR pszRemoteAddr,int iPort,LPCSTR pszLocalAddr=NULL); 
//服务器放建立与客户端的连接 
//pszHost,iPort用于得到对方主机的地址和端口 
extern "C" SOCKET SPCreateAcceptSocket(SOCKET sockListen,char* pszHost=NULL,int *piPort=NULL); 
//创建UDP Socket,对于接收方必须指明端口,发送方可以不指明 
//pszLocalAddr 本地与Socket绑定的地址 
extern "C" SOCKET SPCreateUDPSocket(int iLocalPort=0,LPCSTR pszLocalAddr=NULL); 
 
class CIPCComm 
{ 
public : 
	CIPCComm(){}; 
	~CIPCComm(){}; 
public: 
	//下面的所有函数都可能返回 SP_ERR_GENERAL:表示发生未知错误 
 
	//读:直到完全读入数据,或是错误发生 
	//返回:SP_ERR_SUCCESS,SP_ERR_NETWORK,SP_ERR_GENERAL 
	//iWant:需要读入的字节数 
	//iRead:返回实际读入的字节数 
	virtual int Recv(const int iWant,BYTE* pbBuf,int& iRead)=0; 
 
	//写:直到完全写出数据,或是错误发生 
	//返回:SP_ERR_SUCCESS,SP_ERR_NETWORK,SP_ERR_GENERAL 
	//iWant:需要写出的字节数 
	//iWrote:返回实际写出的字节数 
	virtual int Send(const int iWant,const BYTE *pbBuf,int& iWrote)=0; 
 
	//测试是否有数据到达 
	//返回:SP_ERR_SUCCESS(有数据到达),SP_ERR_NETWORK,SP_ERR_NODATA,SP_ERR_GENERAL 
	//iTimeOut: 超时时间,秒 
	virtual int TestRead(int iTimeOut)=0; 
 
	//测试是否有连接到达 
	//返回:SP_ERR_SUCCESS(有数据到达),SP_ERR_NETWORK,SP_ERR_NODATA(无连接到达),SP_ERR_GENERAL 
	//iTimeOut: 超时时间,秒 
	virtual int TestConnect(int iTimeOut)=0; 
 
	//在规定时间内读入要求数量的数据,尽可能多的读入数据 
	//返回SP_ERR_SUCCESS,SP_ERR_NETWORK,SP_ERR_NOT_FINISH(超时,只读入部分数据),SP_ERR_NODATA(未读入任何数据),SP_ERR_GENERAL 
	virtual int RecvWithTimeOut(int iTimeout,const int iWant,BYTE* pbBuf,int& iRead)=0; 
 
	//检测数据并读入,在检测到数据后只进行一次读操作, 
	//返回:SP_ERR_SUCCESS(读入要求数据),SP_ERR_NETWORK,SP_ERR_NOT_FINISH(检测到数据,但只读入部分数据),SP_ERR_NODATA(超时,未读入任何数据),SP_ERR_GENERAL 
	virtual int TestAndRecv(int iTimeout,const int iWant,BYTE* pbBuf,int& iRead)=0; 
}; 
 
class CIPCSocket: public CIPCComm 
{ 
public: 
	//fAutoDel 是否在删除对象时自动关闭Socket 
	CIPCSocket(SOCKET sockComm,BOOL fAutoDel=FALSE); 
	~CIPCSocket(); 
	SOCKET GetSocket(void){return m_sockComm;}; 
	SOCKET DetachSocket(void){SOCKET s=m_sockComm;m_sockComm=INVALID_SOCKET;return s;}; 
public: 
	//创建Socket helper function 
	static SOCKET CreateListenSocket(LPCSTR pszLocalAddr,UINT uPort) 
	{ 
		return SPCreateListenSocket(pszLocalAddr,uPort); 
	} 
	static SOCKET CreateConnectSocket(LPCSTR pszRemoteAddr,int iPort,LPCSTR pszLocalAddr) 
	{ 
		return SPCreateConnectSocket( pszRemoteAddr, iPort, pszLocalAddr); 
	} 
	static SOCKET CreateUDPSocket(int iLocalPort=0,LPCSTR pszLocalAddr=NULL) 
	{ 
		return SPCreateUDPSocket(iLocalPort,pszLocalAddr); 
	} 
	static SOCKET CreateAcceptSocket(SOCKET sockListen,char* pszHost=NULL,int *piPort=NULL) 
	{ 
		return SPCreateAcceptSocket(sockListen,pszHost,piPort); 
	} 
	// 
	virtual int Recv(const int iWant,BYTE* pbBuf,int& iRead); 
	virtual int Send(const int iWant,const BYTE *pbBuf,int& iWrote); 
	virtual int TestRead(int iTimeOut); 
	virtual int TestConnect(int iTimeOut); 
	static int TestRead(SOCKET sock,int iTimeOut) 
	{ 
		CIPCSocket sTemp(sock,FALSE); 
		return sTemp.TestRead(iTimeOut); 
	}; 
	static int TestConnect(SOCKET sock,int iTimeOut) 
	{ 
		CIPCSocket sTemp(sock,FALSE); 
		return sTemp.TestConnect(iTimeOut); 
	}; 
	virtual int RecvWithTimeOut(int iTimeout,const int iWant,BYTE* pbBuf,int& iRead); 
	virtual int TestAndRecv(int iTimeout,const int iWant,BYTE* pbBuf,int& iRead); 
protected: 
	SOCKET m_sockComm; 
	BOOL m_fAutoDel; 
}; 
//UDP通信类 
class CUDPSocket: public CIPCSocket 
{ 
public: 
	CUDPSocket(SOCKET sockComm,BOOL fAutoDel=FALSE); 
	//取消原有发送、接收函数调用 
	virtual int Recv(const int iWant,BYTE* pbBuf,int& iRead) 
	{VERIFY(FALSE);return SOCKET_ERROR;}; 
	virtual int Send(const int iWant,const BYTE *pbBuf,int& iWrote) 
	{VERIFY(FALSE);return SOCKET_ERROR;}; 
	virtual int TestConnect(int iTimeOut) 
	{VERIFY(FALSE);return SOCKET_ERROR;}; 
	virtual int RecvWithTimeOut(int iTimeout,const int iWant,BYTE* pbBuf,int& iRead) 
	{VERIFY(FALSE);return SOCKET_ERROR;}; 
	virtual int TestAndRecv(int iTimeout,const int iWant,BYTE* pbBuf,int& iRead) 
	{VERIFY(FALSE);return SOCKET_ERROR;}; 
	//允许的函数 
	//发送数据:当发送数据长度过大,时返回:SP_UDP_TOOLONG 
	//pszHost,iPort用于设置对方主机的地址和端口 
	virtual int SendTo(const int iWant,const BYTE* pbBuf,int& iWrote,LPCSTR pszHost,const int iPort); 
	//接收数据,iWant为缓冲区最大长度,如果在接收时该长度过小,会返回:SP_UDP_SMALLBUF 
	//pszHost,iPort用于得到对方主机的地址和端口 
	virtual int RecvFrom(const int iWant,const BYTE* pbBuf,int& iRead,char* pszHost=NULL,int *piPort=NULL); 
 
protected: 
	UINT m_uMaxUDP;//UDP包的最大长度 
}; 
//TCP通信类,在基类上没有经过修改 
class CTCPSocket: public CIPCSocket 
{ 
public: 
	CTCPSocket(SOCKET sockComm,BOOL fAutoDel=FALSE):CIPCSocket(sockComm,fAutoDel) 
	{}; 
 
}; 
 
//pszPipeName \\.\pipe\pipe_name 
//返回 INVALID_HANDLE_VALUE 表明失败 
//创建服务器端管道,并等待连接 
//iTimeout 为等待连接的超时市场,以秒计算 
extern "C" HANDLE SPCreateServerPipe(LPCSTR pszPipeName,int iTimeout=10); 
//创建客户端管道,并连接到服务器端 
//pszPipeName \\server\pipe\pipe_name 
//iTimeout 为超时时长 
extern "C" HANDLE SPCreateClientPipe(LPCSTR pszPipeName,int iTimeout=10); 
 
class CIPCNamedPipe: public CIPCComm 
{ 
public: 
	//fAutoDel 是否在删除对象时自动关闭Socket 
	CIPCNamedPipe(HANDLE hPipe,BOOL fAutoDel=FALSE); 
	~CIPCNamedPipe(); 
	HANDLE GetPipe(void){return m_hPipe;}; 
	HANDLE DetachPipe(void){HANDLE h=m_hPipe;m_hPipe=NULL;return h;}; 
public: 
	static HANDLE CreateServerPipe(LPCSTR pszPipeName,int iTimeout=10) 
	{ 
		return SPCreateServerPipe(pszPipeName,iTimeout); 
	}; 
	static HANDLE CreateClientPipe(LPCSTR pszPipeName,int iTimeout=10) 
	{ 
		return SPCreateClientPipe(pszPipeName,iTimeout); 
	}; 
 
	virtual int Recv(const int iWant,BYTE* pbBuf,int& iRead); 
	virtual int Send(const int iWant,const BYTE *pbBuf,int& iWrote); 
	virtual int TestRead(int iTimeOut); 
	virtual int TestConnect(int iTimeOut); 
	static int TestRead(HANDLE hPipe,int iTimeOut) 
	{ 
		CIPCNamedPipe sTemp(hPipe,FALSE); 
		return sTemp.TestRead(iTimeOut); 
	}; 
	static int TestConnect(HANDLE hPipe,int iTimeOut) 
	{ 
		CIPCNamedPipe sTemp(hPipe,FALSE); 
		return sTemp.TestConnect(iTimeOut); 
	}; 
	virtual int RecvWithTimeOut(int iTimeout,const int iWant,BYTE* pbBuf,int& iRead); 
	virtual int TestAndRecv(int iTimeout,const int iWant,BYTE* pbBuf,int& iRead); 
protected: 
	HANDLE m_hPipe; 
	BOOL m_fAutoDel; 
}; 
 
}//完成名字空间的定义 
#endif