wsocket.h源文件分析

WSAClientSocket继承自ClientSocket,完成对基本WinSock函数的封装。

ClientSocket只是提供一个接口,具体实现由其继承类WSAClientSocket(WINDOWS)和UClientSocket (UNIX)实现

这里先介绍一下Host类:

unsigned int ip; //主机IP

unsigned short port; //主机端口号
 unsigned int value;

下面介绍一下WSAClientSocket的具体实现

//初始化,每个Winsock应用都必须加载合适的WinSock DLL版本.加载库是通过调用WSAStartup函数实现的

void WSAClientSocket::init()
{
 WORD wVersionRequested;
 WSADATA wsaData;
 int err;
   
 wVersionRequested = MAKEWORD( 2, 0 );
 err = WSAStartup( wVersionRequested, &wsaData );
 if ( err != 0 )
  throw SockException("Unable to init sockets");

}

//建立套接字,通过调用socket函数来实现

void WSAClientSocket::open(Host &rh)
{
 sockNum = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);

 if (sockNum == INVALID_SOCKET)
  throw SockException("Can`t open socket");

 setBlocking(false);
#ifdef DISABLE_NAGLE
 setNagle(false);
#endif

 host = rh;

 memset(&remoteAddr,0,sizeof(remoteAddr));

 remoteAddr.sin_family = AF_INET;
 remoteAddr.sin_port = htons(host.port);
 remoteAddr.sin_addr.S_un.S_addr = htonl(host.ip);

}

//服务器绑定。一旦为某种协议创建了套接字,就必须将套接字绑定到一个已知地址上。使用bind函数

void WSAClientSocket::bind(Host &h)
{
 struct sockaddr_in localAddr;

 if ((sockNum = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
  throw SockException("Can`t open socket");

 setBlocking(false);
 setReuse(true);

 memset(&localAddr,0,sizeof(localAddr));
 localAddr.sin_family = AF_INET;
 localAddr.sin_port = htons(h.port);
 localAddr.sin_addr.s_addr = INADDR_ANY;

 if( ::bind (sockNum, (sockaddr *)&localAddr, sizeof(localAddr)) == -1)
  throw SockException("Can`t bind socket");

//接下来要做的,是将套接字置入监听模式。bind函数的作用只是将套接字和指定的地址关联在一起。指示套接字等待连接传入的API是listen

 if (::listen(sockNum,SOMAXCONN))
  throw SockException("Can`t listen",WSAGetLastError());

 host = h;
}

 //现在我们已做好了接受客户机连接的准备,通过ACCEPT函数来完成

ClientSocket *WSAClientSocket::accept()
{

 int fromSize = sizeof(sockaddr_in);
 sockaddr_in from;

 int conSock = ::accept(sockNum,(sockaddr *)&from,&fromSize);


 if (conSock ==  INVALID_SOCKET)
  return NULL;

 
    WSAClientSocket *cs = new WSAClientSocket();
 cs->sockNum = conSock;

 cs->host.port = from.sin_port;
 cs->host.ip = from.sin_addr.S_un.S_un_b.s_b1<<24 |
      from.sin_addr.S_un.S_un_b.s_b2<<16 |
      from.sin_addr.S_un.S_un_b.s_b3<<8 |
      from.sin_addr.S_un.S_un_b.s_b4;


 cs->setBlocking(false);
#ifdef DISABLE_NAGLE
 cs->setNagle(false);
#endif

 return cs;
}

 //关闭套接字

void WSAClientSocket::close()
{
 if (sockNum)
 {
  shutdown(sockNum,SD_SEND);

  setReadTimeout(2000);
  try
  {
   //char c;
   //while (readUpto(&c,1)!=0);
   //readUpto(&c,1);
  }catch(StreamException &) {}

  if (closesocket(sockNum))
   LOG_ERROR("closesocket() error");


  sockNum=0;
 }
}

//客户端连接

 void WSAClientSocket::connect()
{
 if (::connect(sockNum,(struct sockaddr *)&remoteAddr,sizeof(remoteAddr)) == SOCKET_ERROR)
  checkTimeout(false,true);

}

//发送数据

void WSAClientSocket::write(const void *p, int l)
{
 while (l)
 {
  int r = send(sockNum, (char *)p, l, 0);
  if (r == SOCKET_ERROR)
  {
   checkTimeout(false,true); 
  }
  else if (r == 0)
  {
   throw SockException("Closed on write");
  }
  else
  if (r > 0)
  {
   stats.add(Stats::BYTESOUT,r);
   if (host.localIP())
    stats.add(Stats::LOCALBYTESOUT,r);

   updateTotals(0,r);
   l -= r;
   p = (char *)p+r;
  }
 }
}

//接收数据

int WSAClientSocket::read(void *p, int l)
{
 int bytesRead=0;
 while (l)
 {
  int r = recv(sockNum, (char *)p, l, 0);
  if (r == SOCKET_ERROR)
  {
   // non-blocking sockets always fall through to here
   checkTimeout(true,false);

  }else if (r == 0)
  {
   throw EOFException("Closed on read");

  }else
  {
   stats.add(Stats::BYTESIN,r);
   if (host.localIP())
    stats.add(Stats::LOCALBYTESIN,r);
   updateTotals(r,0);
   bytesRead += r;
   l -= r;
   p = (char *)p+r;
  }
 }
 return bytesRead;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值