重构,我的CSTSocket类,NO MFC。

是不是一直在寻找SOCKET这样的功能,所有的,对我是说所有的,都是在限定的时间范围返回结果。SOCKET I/O模型中SELECT模型提供了这样的可能,当然一些超时还要经过一些技巧才行。这是我重构的自己完全动手的第2个可重用类。由于加了#define TIME_INFINITE 0xFFFFFFFF //阻塞模式哈,我第一个包装了的类CBTSocket类可以丢到水桶里去,我可怜的BT~我会记得你的,没有你怎么有我的ST了。

首先是套接字的CREATE哈,CREATE就不用超时了吧根本没这个必要了,因为他马上就返回的

然后LISTEN看来也没必要,也是直接返的,BIND看来也没必要了。接下来有用武之地了。首先是CONNECT超时,这个VCKBASE的精华区有篇文章,取其精华COPY过来实现之哈哈变成了以下方式

int CSTSocket::Connect(const char* szIP, unsigned short nPort, int nSec, int nUSec)

{

if(m_sSocket == NULL)
  return RET_ERRSOCKET;
 
 if( strlen(szIP) == 0 || nPort == 0 )
  return RET_BADPARAM;
 
 m_addr.sin_addr.s_addr = inet_addr(szIP);
 if(INADDR_NONE == m_addr.sin_addr.s_addr)
 {
  return RET_BADPARAM;
 }
 m_addr.sin_family = AF_INET;
 m_addr.sin_port = htons( nPort );


 
 if(nSec == TIME_INFINITE)
 {
  if(connect(m_sSocket, (SOCKADDR*)&m_addr, sizeof(m_addr)) == SOCKET_ERROR )
  {
   return WSAGetLastError();
  }
 }
 else
 {
  //设置为非阻塞方式连接
  unsigned long ul = 1;
  int nRet = ioctlsocket(m_sSocket, FIONBIO, (unsigned long*)&ul);
  if(nRet == SOCKET_ERROR)
  {
   return WSAGetLastError();
  }
  
  FD_SET fd = {1, m_sSocket};
  TIMEVAL tv = {nSec, nUSec};
  
  connect(m_sSocket,(SOCKADDR*)&m_addr, sizeof(m_addr));

  nRet = select(0, 0, &fd, 0, &tv); 
  if(nRet == SOCKET_ERROR)
  {
   return WSAGetLastError();
  }
  
  if(nRet == 0) {
   return RET_TIMEOUT;
  } 
  
  //设回阻塞模式
  ul = 0 ;
  nRet = ioctlsocket(m_sSocket, FIONBIO, (unsigned long*)&ul);
  if(nRet == SOCKET_ERROR)
  {
   return WSAGetLastError();
  }
 }
 return RET_SUCCESS;

}

接下来是ACCEPT,这个好象多此一举,不过自然能实现我就实现吧,闲着也是闲着

int CSTSocket::Accept(CSTSocket &sock, int nSec, int nUSec)
{
 if(m_sSocket == NULL)
  return RET_ERRSOCKET;
 
 SOCKET s;
 sockaddr_in addr;
 int nAddrSize = sizeof(addr);


 FD_SET fd = {1, m_sSocket};
 TIMEVAL tv = {nSec, nUSec};
 int nRet;


 //阻塞模式
 if(nSec != TIME_INFINITE)
 {
  nRet = select(0, &fd, NULL, NULL, &tv);
  if(nRet == SOCKET_ERROR)
  {
   return WSAGetLastError();
  }
  
  if(nRet == 0)
  {
   return RET_TIMEOUT;
  } 
 }

 if((s = accept(m_sSocket, (SOCKADDR*)&addr, &nAddrSize)) == INVALID_SOCKET )
 {
  return WSAGetLastError();
 }
 sock.SetContent(s, addr);
 

 return RET_SUCCESS;

}

开始在网上找时候并没有找到相关的,但看到SDK

readfds:If listening, a connection is pending, accept will succeed

于是我如上事项,也成功了。

接下来是发送,因为有个缓冲区可以轮刷~

int CSTSocket::Send(const char *szData, int nLen, int nSec, int nUSec)
{
 if(m_sSocket == NULL)
  return RET_ERRSOCKET;
 
 if( szData == NULL || nLen == 0 )
  return RET_BADPARAM;
 
 
 int nRet = 0;
 int nSent = 0;
 int nLeft = 0;
 int nIdx = 0;
 nLeft = nLen;

 if(nSec == TIME_INFINITE)
 {
  while(nLeft > 0)
  {
   nSent = send(m_sSocket, szData + nIdx, nLeft, 0);
   if(nSent == SOCKET_ERROR)
   {
    return WSAGetLastError();
   }
   
   if(nSent == 0)
   {
    return RET_SOCKCLOSED;
   }
   
   nLeft -= nSent;
   nIdx  += nSent;
  }

 }
 else
 {
  FD_SET fd = {1, m_sSocket};
  TIMEVAL tv = {nSec, nUSec};
  
  while(nLeft > 0)
  {
   nRet = select(0, NULL, &fd, NULL, &tv);
   if (SOCKET_ERROR == nRet)
   {
    return WSAGetLastError();
   }
   if(nRet == 0)
   {
    return RET_TIMEOUT;
   }
   
   nSent = send(m_sSocket, szData + nIdx, nLeft, 0);
   if(nSent == SOCKET_ERROR)
   {
    return WSAGetLastError();
   }
   
   if(nSent == 0) {
    return RET_SOCKCLOSED;
   }
   
   nLeft -= nSent;
   nIdx  += nSent;
  }

 }

 
 return RET_SUCCESS;
 

}

接下来接受,一次接受,

int CSTSocket::Recv(char *szData, int nLen, int *pnRecvLen, int nSec, int nUSec)
{
 if(m_sSocket == NULL)
  return RET_ERRSOCKET;
 
 if( szData == NULL )
  return RET_BADPARAM;

 //假如不是阻塞等待的话
 if(nSec != TIME_INFINITE)
 {
  int nRet;
  FD_SET fd = {1, m_sSocket};
  TIMEVAL tv = {nSec, nUSec};
  
  
  nRet = select(0, &fd, NULL, NULL, &tv);
  if (SOCKET_ERROR == nRet)
  {
   return WSAGetLastError();
  }
  
  if(nRet == 0)
  {
   return RET_TIMEOUT;
  }

 }

 *pnRecvLen = recv(m_sSocket, szData, nLen, 0);
 if (*pnRecvLen == SOCKET_ERROR)
 {
  return WSAGetLastError();
 }
 if (0 == *pnRecvLen)
 {
  return RET_SOCKCLOSED;
 }
 
 return RET_SUCCESS;
}

最后加了个函数,接受固定子节数的,如果接受不到,最后会超时。

www.lwkl.net/SELECT模型SOCKET.rar

经过测试写了个简单的服务器和客户机

谢谢大家捧场希望大家喜欢,有错误请告知。

写完这个类,测试成功后,我又找到了久违的快感~哈~~~~~~~~~~~`

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值