⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 csocket.h

📁 sun Linux 下的网络编程
💻 H
字号:
/*******************************************************************
*	cSocket.h
*    DESCRIPTION:
*
*    AUTHOR:yyc---yycmail@263.sina.com
*			http://yycnet.yeah.net
*
*    HISTORY:
*
*    DATE:2002-8-19
*
*******************************************************************/

#ifndef __CSOCKET_H__
#define __CSOCKET_H__

#include "osdef.h"

#include "cThread.h"
#include "cBuffer.h"
#include "cFifo.h"
#include <deque>
#include <map>


namespace yyc
{
#define EFULL_SOCK -1
#define ENULL_SOCK -2
#define EHANDLE_SOCK -3 //非法的socket 句柄
#define EMEM_SOCK -4 //创建对象失败/内存分配错误
#define ELIMIT_SOCK -5 //不能创建cSocket客户对象,超过Server的最大连接客户端限制数
#define ETHREAD_SOCK -6 //启动发送或接收线程出错或线程未启动
#define EARGS_SOCK -7 //传递参数错误
#define ECONN_SOCK -8 //连接指定的主机失败或此Csocket对象未连接
#define ESOCKET_SOCK -9 //创建socket失败
#define ESETOPT_SOCK -10 //调用setsockopt发生错误
#define EBIND_SOCK -11
#define ELISTEN_SOCK -12 
#define OK_SOCK 0

//socket 接收线程回调函数--数据处理函数
//第一个参数为接收数据缓冲指针,第二个参数为接收数据的长度
//第三个参数为接收此数据的cSocket对象指针
//返回值为int型
//第1位指示是否关闭SOCKET连接,第2位指示关闭SOCKET连接是否等待缓冲区数据发送完成
class cSocket;
typedef int(FUNC_DODATA)(char *,int ,cSocket *); 

class cSocket
{
private:
	//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
	//保存cSocket服务对象的连接客户端的多线程安全集合
	class clients
	{
	private:
		//int为一个整型数,标识csocket对象
		std::map<cSocket *,int> m_set;
		//自增长的唯一标识csocket对象的整数
		int m_hSocket;
		cMutex m_mutex;
		static const int MAX_CLIENT_NUM;//=50;
	public:
		clients();
		int del(cSocket *psock);
		int remove(cSocket *psock);
		int add(cSocket *psock);
		void clear();
		cSocket *get(int index);
		~clients();
		int len()
		{
			return m_set.size();
		}
	   
	};
	//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
	clients m_client_set;

	int m_fd;//socket handle,default -1
	char m_strHostip[20];//remote host ip
	int m_iHostport;//remote host port
	char m_strLocalip[20];//local host ip
	int m_iLocalport;//local host port
	int m_iStatus; //cSocket object status,SOCK_CLOSED:SOCK_CONNECTED:SOCK_LISTEN
	int m_iType; //cSocket IP type 0-tcp 1-udp
	int m_iComm; //cSocket communication type 0-none 1-recv 2-send 3-dual
	bool m_bAutoclose;//auto close cSocket object if output buffer is empty
	cThread m_recvThread;
	cThread m_sendThread;
    cFifo<cBuffer> m_in_buf;  //接受缓冲区
	cFifo<cBuffer> m_out_buf; //发送缓冲区

    cSocket * m_pParent; //server cSocket object's point of creating this cSocket object 
    FUNC_DODATA * m_pfDodata;  //function point of deal with received data
	//记录外部对象对此cSocket对象的引用
	//如果socket连接发生异常或中断,当外部引用计数为<=0时,则自动删除释放cSocket对象
	int m_iRef;//cSocket object引用计数,default=1
	void * m_pArgs;//point of other data that cSocket object request

public:
    enum
	{
		SOCK_CLOSED,
		SOCK_CONNECTED,
		SOCK_LISTEN //侦听服务或客户服务状态
	};
private:
    //接收线程
	static int recv_thread(void *args);
	//发送线程
	static int send_thread(void *args);
	//启动收发线程
	int start_thread();
    /**
	 * 检查socket是否有数据到达f=0
	 * 检查socket是否可写 f=1
	 * 
	 * @param wait_usec 最大超时等待时间(us)
	 * 
	 * @return =0:没有数据
	 *         >0:有数据可读,或socket可写
	 *         <0:socket发生错误
	 */
   int checkdata(long wait_usec,int f=0);
   /**
	 * 用指定的socket连接句柄初始化或创建cSocket客户对象
	 * 
	 * @param fd       指定的socket连接句柄
	 * @param remoteip   socket连接的主机IP
	 * @param remoteport socket连接的主机侦听端口
	 * 
	 * @return <0:发生错误
	 *         >=0:连接成功
	 *         如果此csocket对象为服务csocket,则自动创建一个普通csocket客户
	 *         连接指定的主机,并将此csocket对象保存到csocket服务对象的客户端缓冲区中,返回
	 *         新创建的csocket对象的句柄(从1开始)
	 *         如果为普通csocket客户对象,则返回0
	 */
	int createClient(int fd,const char *remoteip,int remoteport);
	/**
	 * 从输入/输出缓冲区中的取数据
	 * 
	 * @param buf     接收缓冲区数据地址空间
	 * @param size   接收缓冲区的最大长度
	 * @inORout 	 0--输入缓冲区 1--输出缓冲区
	 * @return 返回接收的数据大小
	 */
	int getdata(char *buf,int size,int inORout);
public:
	cSocket();
	~cSocket();
    /**
	 * 发送数据到输出缓冲区
	 * 
	 * @param fmt    格式化字符串
	 * 
	 * @return 发送数据个数,<0发生错误
	 */
	int send(const char * fmt,...);
	/**
	 * 发送数据到输出缓冲区
	 * 
	 * @param len    发送数据大小
	 * @param buf    发送数据指针
	 * 
	 * @return 发送数据个数,<0发生错误
	 */
	int send(int len,const char * buf);
	/**
	 * 发送数据到输出缓冲区
	 * 当函数成功时,将更改*ppBuf=NULL,防止调用者释放*ppBuf空间
	 * 
	 * @param len    发送数据大小
	 * @param buf    发送数据指针的指针
	 * 
	 * @return 发送数据个数,<0发生错误
	 */
	int send(int len,char ** ppBuf);
	/**
	 * 发送数据到输出缓冲区
	 * 当函数成功时,将更改*ppBuf=NULL,防止调用者释放*ppBuf空间
	 * 
	 * @param len    发送数据大小
	 * @param buf    发送数据指针的指针
	 * 
	 * @return 发送数据个数,<0发生错误
	 */
	int send(cBuffer **ppBuf);
	/**
	 * 接收输入缓冲区中的数据
	 * 
	 * @param buf     接收缓冲区数据地址空间
	 * @param size   接收缓冲区的最大长度
	 * 
	 * @return 返回接收的数据大小
	 */
	int recv(char *buf,int size);

	/**
	 * 接收输入缓冲区中的数据
	 * 此函数将分配内存接收输入缓冲区的数据,并将分配的内存指针写入ppBuf变量中返回
	 * 
	 * @param ppBuf   保存接收缓冲区指针的地址指针
	 * 
	 * @return 返回接收的数据大小
	 */
	int recv(char **ppBuf);
	
	/**
	 * 接收输入缓冲区中的数据
	 * 
	 * @param pbuf   接收数据的buffer对象
	 * 
	 * @return <0,发生错误
	 *         返回接收的数据大小
	 */
	int recv(cBuffer *pbuf);
	/**
	 * 往接收缓冲区中插入数据
	 * 
	 * @param buf    插入数据的指针
	 * @param len    插入数据大小
	 * 
	 * @return 插入数据大小
	 *         <0 发生错误
	 */
	int fill(const char * buf,int len);

	/**
	 * 将*ppBuf指向的对象压入接收缓冲区堆栈
	 * 当函数成功时,将更改*ppBuf=NULL,防止调用者释放*ppBuf空间
	 * 
	 * @param ppBuf   要压入接收缓冲区的cBuffer对象指针的指针
	 * 
	 * @return <0,发生错误
	 *         插入数据大小
	 */
	int fill(cBuffer **ppBuf);
    /**
	 * 连接指定的主机
	 * 
	 * @param remoteip   主机IP
	 * @param remoteport 主机侦听端口
	 * 
	 * @return <0:发生错误
	 *         >=0:连接成功
	 * 			返回cSocket对象的句柄,客通过get_pSocket()函数返回cSocket对象的指针
	 */
	int connect(const char * remoteip,int remoteport);
	int close();
    /**
	 * 创建侦听服务cSocket对象
	 * 
	 * @param iPort 侦听服务端口
	 *               >=0启动服务并在指定的端口进行侦听
	 * 				如果=0,则系统自动分配侦听服务端口,否则用用户指定的端口
	 *               <0,启动服务,但不进行侦听
	 * 
	 * @return <0:发生错误
	 * 		否则返回侦听端口
	 */
	int listen(int iPort=0);
	
	int status()
	{
		return m_iStatus;
	}

	/**
	 * 返回指定句柄的cSocket对象指针,并增加引用计数
	 * 
	 * @param hSocket
	 * 
	 * @return 
	 */
	cSocket *get_pSocket(int hSocket)
	{
		cSocket *psock=NULL;
		if(hSocket<0)
		{
			m_iRef--;
			psock=this;
		}
		else if(hSocket==0)
		{
			m_iRef++;
			psock=this;
		}
		else
		{
			//this object is Server object
			psock=m_client_set.get(hSocket);
			if(psock!=NULL)
				psock->m_iRef++;
		}
		return psock;
	}

	int get_localhost_info(char **strLocalip=NULL)
	{
		if(strLocalip!=NULL) *strLocalip=m_strLocalip;
		return m_iLocalport;
	}
	int get_remotehost_info(char **strRemoteip=NULL)
	{
		if(strRemoteip!=NULL) *strRemoteip=m_strHostip;
		return m_iHostport;
	}
	void set_pfDodata(FUNC_DODATA *pf)
	{
		m_pfDodata=pf;
	}
	void set_pArgs(void *pArgs)
	{
		m_pArgs=pArgs;
	}
	void *get_pArgs()
	{
		return m_pArgs;
	}
	void set_bAutoclose(bool b)
	{
		m_bAutoclose=b;
	}
	bool get_bAutoclose()
	{
		return m_bAutoclose;
	}
	//查看输出/输入缓冲是否为空
	//f=0,输出缓冲 =1输入缓冲
	bool isEmpty(int f=0)
	{
        bool bRet;
		if(f==0)
			bRet=m_out_buf.empty();
		else
			bRet=m_in_buf.empty();
		return bRet;
	}
    /**
	 * 清空缓冲区
	 * 
	 * @param f      指明要清空的缓冲区
	 *               -1----all
	 *               0----不清空
	 *               1----接收缓冲区
	 *               2----发送缓冲区
	 *               4----客户端对象缓冲区
	 */
	void clear(int f=0)
	{
        if((f & 1)!=0) m_in_buf.clear();
		if((f & 2)!=0) m_out_buf.clear();
		if((f & 4)!=0) m_client_set.clear();
	}
};



//redefine my_usleep() replace usleep()
//有的操作系统没有usleep()函数
//同时usleep()在SUN unix下有可能导致永久阻塞
//因此将对系统的usleep函数的调用改为自建的函数调用
inline void my_usleep(unsigned int us)
{
	struct timeval to;
	to.tv_sec = 0;
	//引该加保护,us必须>=0且小于1000000
	//为了提高效率,此保护由调用者提供
	to.tv_usec = us;
	select(0, NULL, NULL, NULL, &to);
}

}//namespace yyc

#endif




⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -