📄 csocket.cpp
字号:
{
//如果此cSocket对象已经处于连接状态,则先关闭
if(sckStatus==SOCK_CONNECTED) close();
psock=this;
}
psock->m_iHostport=remoteport;
if(remoteip!=NULL)
strncpy(psock->m_strHostip,remoteip,19);
psock->m_strHostip[19]=0;
psock->m_fd=fd;
RW_LOG_DEBUG("create cSocket client successfully,connected %s:%d,sock_comm=%d\n",psock->m_strHostip,psock->m_iHostport,psock->m_iComm);
//获取本地端IP和端口
addr_len=sizeof(addr);
if (getsockname(psock->m_fd,(struct sockaddr *) &addr,(socklen_t *)&addr_len)==0)
{
if (0==psock->m_iLocalport) psock->m_iLocalport=addr.sin_port;
ptr=(char *)inet_ntoa(addr.sin_addr);
if (psock->m_strLocalip[0]==0&&ptr!=NULL)
{
strncpy(psock->m_strLocalip,ptr,19);
psock->m_strLocalip[19]=0;
}
}
psock->m_iStatus=SOCK_CONNECTED;
if (sckStatus==SOCK_LISTEN)
{
if(m_client_set.add(psock)<0)
{
RW_LOG_WARN("Can not add cSocket client because of limit,server(port:%d) have %d clients.\n",get_localhost_info(),m_client_set.len());
retv=ELIMIT_SOCK;
}
else
{
psock->m_pParent=this;
RW_LOG_DEBUG("server(port:%d) have %d clients in clnt_buf!!!\n",get_localhost_info(),m_client_set.len());
}
}//?if (m_status==SOCK_LISTEN)
if(retv>=0)
{
if (psock->start_thread()!=0) {
RW_LOG_ERROR("starting recv/send thread failed!\n");
retv=ETHREAD_SOCK;
}
}
if (retv<0) {
fd=psock->m_fd;
psock->m_fd=-1;
psock->m_iStatus=SOCK_CLOSED;
if(fd>=0) ::closesocket(fd);
//删除动态创建的cSocket对象
if (sckStatus==SOCK_LISTEN) delete psock;
}
return retv;
}
/**
* 连接指定的主机
*
* @param remoteip 主机IP
* @param remoteport 主机侦听端口
*
* @return <0:发生错误
* >=0:连接成功
* 返回cSocket对象的句柄,客通过get_pSocket()函数返回cSocket对象的指针
*/
int cSocket::connect(const char * remoteip,int remoteport)
{
int retv;
int fd;
struct sockaddr_in addr;
if (remoteport<=0||remoteip==NULL||remoteip[0]==0) {
return EARGS_SOCK;
}
if((fd=::socket(AF_INET,SOCK_STREAM,0))>=0)
{
addr.sin_family = AF_INET;
addr.sin_port = htons(remoteport);
addr.sin_addr.s_addr=inet_addr((const char *)remoteip);
retv=::connect(fd, (struct sockaddr *) &addr, sizeof(addr));
if(retv==0)
retv=createClient(fd,remoteip,remoteport);
else
{
retv=ECONN_SOCK;
::closesocket(fd);
}
}
else
retv=ESOCKET_SOCK;
return retv;
}
/**
* 创建侦听服务cSocket对象
*
* @param iPort 侦听服务端口
* >=0启动服务并在指定的端口进行侦听
* 如果=0,则系统自动分配侦听服务端口,否则用用户指定的端口
* <0,启动服务,但不进行侦听
*
* @return <0:发生错误
*/
int cSocket::listen(int iPort)
{
int retv=OK_SOCK;
if(m_iStatus!=SOCK_CLOSED) close();
if (m_fd<0) m_fd=socket(AF_INET,SOCK_STREAM,0);
if (m_fd<0) return ESOCKET_SOCK;
if (iPort<0)
{
//create client-server cSocket
//do not start threads
m_iComm=0;
m_iType=0;//tcp
RW_LOG_DEBUG("Client-Server have started!\n");
}
else
{
int reuse=1;
int addr_len;
struct sockaddr_in addr;
m_iLocalport=iPort;
if (setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, (char *) &reuse,sizeof(reuse)) == -1)
retv=ESETOPT_SOCK;
else
{
addr.sin_family = AF_INET;
addr.sin_port = htons(m_iLocalport);
if (m_strLocalip[0]==0)
{
//获取本机IP
char buf[50];buf[0]=0;
gethostname(buf,50);
struct hostent * p=gethostbyname(buf);
if (p!=NULL&&buf[0]!=0)
addr.sin_addr=*((struct in_addr *)p->h_addr);
else
addr.sin_addr.s_addr=htonl(INADDR_ANY);
strcpy(m_strLocalip,(char *)inet_ntoa(addr.sin_addr));
}
else
addr.sin_addr.s_addr=inet_addr((const char *)m_strLocalip);
if (bind(m_fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
retv=EBIND_SOCK;
else
{
if (::listen(m_fd, 50) == -1)
retv=ELISTEN_SOCK;
else
{
//getsockname()函数用于获取一个套接口的名字。它用于一个已捆绑或已连接套接口s,本地地址将被返回。
//本调用特别适用于如下情况:未调用bind()就调用了connect(),
//这时唯有getsockname()调用可以获知系统内定的本地地址。
//在返回时,namelen参数包含了名字的实际字节数。
//若一个套接口与INADDR_ANY捆绑,也就是说该套接口可以用任意主机的地址,
//此时除非调用connect()或accept()来连接,否则getsockname()将不会返回主机IP地址的任何信息。
//除非套接口被连接,WINDOWS套接口应用程序不应假设IP地址会从INADDR_ANY变成其他地址。
//这是因为对于多个主机环境下,除非套接口被连接,否则该套接口所用的IP地址是不可知的。
if (m_iLocalport==0)
{
addr_len=sizeof(addr);
if (getsockname(m_fd,(struct sockaddr *) &addr,(socklen_t *)&addr_len)==0)
m_iLocalport=ntohs(addr.sin_port);
}
m_iComm=1;//server只能收,即接受客户端连接
m_iType=0;//tcp
m_iStatus=SOCK_LISTEN;
retv=m_iLocalport;
if (start_thread()!=0)
{
close();
retv=ETHREAD_SOCK;//启动接受和发送数据线程
}
else
{
RW_LOG_DEBUG("Listen-Server have started,port=%d\n",retv);
}
}//?if (listen(sock_fd, 50) == -1) else
}//?if (bind(sock_fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) else
}//?if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, (char *) &reuse,sizeof(reuse)) == -1) else
}//?if (iPort<0) else
return retv;
}
/**
* 发送数据到输出缓冲区
*
* @param fmt 格式化字符串
*
* @return 发送数据个数,<0发生错误
*/
int cSocket::send(const char * fmt,...)
{
char buf[DEFAULT_BUF_SIZE];//vc++ not surpport char[cBuffer::MAX_BUF_SIZE]
buf[cBuffer::MAX_BUF_SIZE-1]=0;
va_list args;
va_start(args,fmt);
vsnprintf(buf,cBuffer::MAX_BUF_SIZE,fmt,args);
va_end(args);
return send(strlen(buf),buf);
}
/**
* 发送数据到输出缓冲区
*
* @param len 发送数据大小
* @param buf 发送数据指针
*
* @return 发送数据个数,<0发生错误
*/
int cSocket::send(int len,const char * buf)
{
int retv=0;
if (m_fd<0) return EHANDLE_SOCK;
if (!m_sendThread.status()) return ETHREAD_SOCK;
if (m_iStatus!=SOCK_CONNECTED) return ECONN_SOCK;
if (NULL==buf||len<=0) return ENULL_SOCK;
auto_ptr<cBuffer> pbuf(new(nothrow) cBuffer(buf,len));
if(pbuf.get()!=NULL&&pbuf->len()>0)
{
m_out_buf.push (pbuf.release());
retv=len;
}
else
retv=EMEM_SOCK;
return retv;
}
/**
* 发送数据到输出缓冲区
* 当函数成功时,将更改*ppBuf=NULL,防止调用者释放*ppBuf空间
*
* @param len 发送数据大小
* @param buf 发送数据指针的指针
*
* @return 发送数据个数,<0发生错误
*/
int cSocket::send(int len,char ** ppBuf)
{
int retv=0;
if (m_fd<0) return EHANDLE_SOCK;
if (!m_sendThread.status()) return ETHREAD_SOCK;
if (m_iStatus!=SOCK_CONNECTED) return ECONN_SOCK;
if (NULL==ppBuf||(*ppBuf)==NULL||len<=0) return ENULL_SOCK;
auto_ptr<cBuffer> pbuf(new(nothrow) cBuffer);
if(pbuf.get()!=NULL)
{
pbuf->set(*ppBuf,len);
m_out_buf.push (pbuf.release());
*ppBuf=NULL;
retv=len;
}
else
retv=EMEM_SOCK;
return retv;
}
/**
* 发送数据到输出缓冲区
* 当函数成功时,将更改*ppBuf=NULL,防止调用者释放*ppBuf空间
*
* @param len 发送数据大小
* @param buf 发送数据指针的指针
*
* @return 发送数据个数,<0发生错误
*/
int cSocket::send(cBuffer **ppBuf)
{
int retv=0;
if (m_fd<0) return EHANDLE_SOCK;
if (!m_sendThread.status()) return ETHREAD_SOCK;
if (m_iStatus!=SOCK_CONNECTED) return ECONN_SOCK;
if (NULL==ppBuf||(*ppBuf)==NULL) return ENULL_SOCK;
m_out_buf.push(*ppBuf);
*ppBuf=NULL;
return retv;
}
/**
* 接收输入缓冲区中的数据
*
* @param buf 接收缓冲区数据地址空间
* @param size 接收缓冲区的最大长度
*
* @return 返回接收的数据大小
*/
int cSocket::recv(char *buf,int size)
{
return getdata(buf,size,0);
}
/**
* 接收输入缓冲区中的数据
* 此函数将分配内存接收输入缓冲区的数据,并将分配的内存指针写入ppBuf变量中返回
*
* @param ppBuf 保存接收缓冲区指针的地址指针
*
* @return 返回接收的数据大小
*/
int cSocket::recv(char **ppBuf)
{
if(ppBuf==NULL) return ENULL_SOCK;
cBuffer buf;
cBuffer *ptemp=m_in_buf.peek();
while(ptemp!=NULL)
{
buf.append(ptemp->get(),ptemp->len());
delete ptemp;
m_in_buf.pop();
ptemp=m_in_buf.peek();
}
*ppBuf=buf.release();
return buf.len();
}
/**
* 接收输入缓冲区中的数据
*
* @param pbuf 接收数据的buffer对象
*
* @return <0,发生错误
* 返回接收的数据大小
*/
int cSocket::recv(cBuffer *pbuf)
{
if(pbuf==NULL) return ENULL_SOCK;
cBuffer *ptemp=m_in_buf.peek();
while(ptemp!=NULL)
{
pbuf->append(ptemp->get(),ptemp->len());
delete ptemp;
m_in_buf.pop();
ptemp=m_in_buf.peek();
}
return pbuf->len();
}
/**
* 往接收缓冲区中插入数据
*
* @param buf 插入数据的指针
* @param len 插入数据大小
*
* @return 插入数据大小
* <0 发生错误
*/
int cSocket::fill(const char * buf,int len)
{
int retv=0;
if (NULL==buf||len<=0) return ENULL_SOCK;
auto_ptr<cBuffer> pbuf(new(nothrow) cBuffer(buf,len));
if(pbuf.get()!=NULL&&pbuf->len()>0)
{
m_in_buf.push (pbuf.release());
retv=len;
}
else
retv=EMEM_SOCK;
return retv;
}
/**
* 将*ppBuf指向的对象压入接收缓冲区堆栈
* 当函数成功时,将更改*ppBuf=NULL,防止调用者释放*ppBuf空间
*
* @param ppBuf 要压入接收缓冲区的cBuffer对象指针的指针
*
* @return <0,发生错误
* 插入数据大小
*/
int cSocket::fill(cBuffer **ppBuf)
{
int retv=0;
if(ppBuf==NULL||(*ppBuf)==NULL) return ENULL_SOCK;
retv=(*ppBuf)->len();
m_in_buf.push(*ppBuf);
*ppBuf=NULL;
return retv;
}
//************************************************************************************
//**************************cSocket::clients***************************************************
const int cSocket::clients::MAX_CLIENT_NUM=50;
cSocket::clients::clients()
{
m_hSocket=0;
}
int cSocket::clients::del(cSocket *psock)
{
int retv=0;
if(psock!=NULL)
{
m_mutex.lock();
if(!m_set.empty())
{
m_set.erase(psock);
retv=m_set.size();
}
m_mutex.unlock();
delete psock;
}
else
retv=ENULL_SOCK;
return retv;
}
int cSocket::clients::remove(cSocket *psock)
{
int retv=0;
if(psock!=NULL)
{
m_mutex.lock();
if(!m_set.empty())
{
m_set.erase(psock);
retv=m_set.size();
}
m_mutex.unlock();
}
else
retv=ENULL_SOCK;
return retv;
}
int cSocket::clients::add(cSocket *psock)
{
int retv=0;
if (psock!=NULL) {
m_mutex.lock();
if(m_set.size()<MAX_CLIENT_NUM)
{
if(m_hSocket>=0x7fffffff) m_hSocket=0;
retv=++m_hSocket;
m_set[psock]=retv;
}
else
retv=EFULL_SOCK;
m_mutex.unlock();
}
else
retv=ENULL_SOCK;
return retv;
}
void cSocket::clients::clear()
{
cSocket *aPsock[MAX_CLIENT_NUM];
int i=0;
m_mutex.lock();
if(!m_set.empty())
{
map<cSocket *,int>::iterator it=m_set.begin();
for(;it!=m_set.end();it++)
aPsock[i++]=(*it).first;
m_set.clear();
}
m_mutex.unlock();
while(i>0)
delete aPsock[--i];
}
cSocket * cSocket::clients::get(int index)
{
cSocket *psock=NULL;
if(index<=0) return NULL;
m_mutex.lock();
if(!m_set.empty())
{
map<cSocket *,int>::iterator it=m_set.begin();
for(;it!=m_set.end();it++)
{
if(index==(*it).second)
{
psock=(*it).first;
break;
}
}
}
m_mutex.unlock();
return psock;
}
cSocket::clients::~clients()
{
clear();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -