CSDN博客

img coolcol

CTcp基本网络通讯封装类

发表于2004/10/22 19:53:00  2635人阅读


// Tcp.h: 基本网络通讯封装类
//
//////////////////////////////////////////////////////////////////////

#ifndef __TCP_H__
#define __TCP_H__

#include <winsock.h>
#pragma comment(lib, "wsock32.lib")  // search for wsock32 lib at compile time

#define WM_TCP  WM_APP+100

class CTcp 
{
public:
 CTcp();
 ~CTcp();


 //extern int sd_connect, sd_bind, sd_accept;
 int wsa_ok ;
 static void peek_message(void);
 static int get_local_ip(char *ip);
 
 int init();
 int exit();

 int bind_listen(int port,sockaddr_in& addr,long &err);
 
 int status(int  sd, char *type, int timeout=5);
 int bind(HWND hWnd, int port);
 int bind2(HWND hWnd, char *ip, int port);
 int accept(int sd, int timeout);
 int connect(char *hostname, int port, int timeout, int f_noblock);
 int connect2(char *bind_ip, char *hostname, int port, int timeout, int f_noblock);
 void disconnect(int sd);
 void close(int& sd);

 
 int send(int sd, char *buf, int len, int timeout=10);
 int recv(int sd, char *buf, int len, int timeout=10);
 int gethostnamebyip(char *ip, char *name);
 
 unsigned short htons(unsigned short);
 unsigned short ntohs(unsigned short);
 unsigned long int htonl(unsigned long int);
 unsigned long int ntohl(unsigned long int);
 unsigned __int64 ntohh(unsigned __int64);
 unsigned __int64 htonh(unsigned __int64);
 
 float htonf(float f);
 float ntohf(float f);
 double htond(double d);
 double ntohd(double d);
 
 char *get_remote_ip(int sd, char *ip);
 
};

#endif

------------------------------------------------------
// Tcp.cpp: implementation of the CTcp class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include <winsock.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include "tcp.h"

extern WriteLog(char *file_name, char *format, ...);
extern WriteStat(char *format, ...);

 

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CTcp::CTcp()
{
 wsa_ok =0;
}

CTcp::~CTcp()
{

}

 

 

int CTcp::init()
{
 if(!wsa_ok)
 {
  WSAData wsa;

  //sd_bind =sd_connect =sd_accept =-1;
  if(WSAStartup(MAKEWORD(1, 1), &wsa) !=0)
   return -1;
  wsa_ok =1;
 }
 return 0;
}

int CTcp::exit()
{
  if(wsa_ok) WSACleanup();

  return 0;
}

int CTcp::status(int  sd, char *type, int timeout)
{
  fd_set rset, wset, eset;
  fd_set FAR *prset =NULL, *pwset =NULL, *peset =NULL;
  struct timeval tval;
  int i, status, err_no =0;
  time_t t1, t2;
  MSG msg;

  tval.tv_sec =0;
  tval.tv_usec =1;
  time(&t1);
  t2 =t1;
  while(t2-t1 < timeout)
  {
    FD_ZERO(&rset);
    FD_ZERO(&wset);
    FD_ZERO(&eset);

    for(i =0; i<(int)strlen(type); i++)
    {
      if(type[i] =='r') { FD_SET(sd, &rset); prset =&rset; }
      if(type[i] =='w') { FD_SET(sd, &wset); pwset =&wset; }
      if(type[i] =='e') { FD_SET(sd, &eset); peset =&eset; }
    }
    status =select(-1, prset, pwset, peset, &tval);
 err_no =WSAGetLastError();
 int err=GetLastError();
 //WriteStat("select err_no=%d, err=%d", err_no, err);
    time(&t2);
 if(status ==0)
    {
      if(PeekMessage(&msg, 0, NULL, NULL, PM_REMOVE))
      {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
        if(msg.message ==WM_QUIT)
  {
   //WSASetLastError(WSAETIMEOUT);
   return -1;
  }
      }
      if(t2-t1 <timeout) continue;
      else
      {
        if(prset) FD_CLR((UINT)sd,&rset);
        if(pwset) FD_CLR((UINT)sd,&wset);
        if(peset) FD_CLR((UINT)sd,&eset);
        WSASetLastError(WSAEWOULDBLOCK);
        return -10;
      }
    }

    if(peset && FD_ISSET(sd, peset))
    {
      if(prset !=NULL) FD_CLR((UINT)sd,&rset);
      if(pwset !=NULL) FD_CLR((UINT)sd,&wset);
      if(peset !=NULL) FD_CLR((UINT)sd,&eset);
      //err_no =WSAGetLastError();
      /*
      len =sizeof(errno);
      getsockopt(sd, SOL_SOCKET, SO_ERROR, (char *)&errno, &len);
      */
   WSASetLastError(err_no);
      return -1;
    }
    if((prset && FD_ISSET(sd, prset)) || (pwset && FD_ISSET(sd, pwset)))
    {
      //err_no =WSAGetLastError();
      /*
      len =sizeof(errno);
      getsockopt(sd, SOL_SOCKET, SO_ERROR, (char *)&errno, &len);
      */
    }
    if(prset !=NULL) FD_CLR((UINT)sd,&rset);
    if(pwset !=NULL) FD_CLR((UINT)sd,&wset);
    if(peset !=NULL) FD_CLR((UINT)sd,&eset);

    //if(status <0)
      //err_no =WSAGetLastError();
 WSASetLastError(err_no);
    if(err_no ==WSAEINTR)
 {
  return WSAEINTR;
 }
    if(err_no)
    {
      return -1;
    }
    else break;
  }

  return 0;
}

int CTcp::bind(HWND hWnd, int port)
{
 struct sockaddr_in addr;
    char temp[200];
    int sd;

    sd =-1;
 if((sd =socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) <0)
 {
  sprintf(temp, "socket failed! errno:%d", WSAGetLastError());
  return -1;
 }

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

 addr.sin_family =AF_INET;
 addr.sin_port =htons((unsigned short)port);
    int l =1;
    setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&l, sizeof(l));
    /*setsockopt(sd, SOL_SOCKET, SO_REUSEPORT, (char *)&l, sizeof(l));*/
 if(::bind(sd, (struct sockaddr *)&addr, sizeof(addr)) <0)
 {
      sprintf(temp, "bind failed! errno:%d", WSAGetLastError());
   closesocket(sd);
      return -1;
 }
 if(hWnd && WSAAsyncSelect(sd, hWnd, WM_TCP, FD_ACCEPT) !=0)
    {
      sprintf(temp, "tcp_bind:WSAAsyncSelect failed!");
      closesocket(sd);
      return -2;
    }
    //sd_bind =sd;
    listen(sd, 5);
    return sd;
}

int CTcp::bind2(HWND hWnd, char *ip, int port)
{
 struct sockaddr_in addr;
    char temp[200];
    int sd;

    sd =-1;
 if((sd =socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) <0)
 {
  sprintf(temp, "socket failed! errno:%d", WSAGetLastError());
  return -1;
 }

 if(ip && *ip)
 {
  memset(&addr, 0, sizeof(addr));
  ULONG ul =inet_addr(ip);
  if(ul ==0xffffffff)
  {
   closesocket(sd);
   return -1;
  }
  else addr.sin_addr.s_addr=ul;
 }
 
 memset(&addr, 0, sizeof(addr));

 addr.sin_family =AF_INET;
 addr.sin_port =htons((unsigned short)port);
    int l =1;
    setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&l, sizeof(l));
    /*setsockopt(sd, SOL_SOCKET, SO_REUSEPORT, (char *)&l, sizeof(l));*/
 if(::bind(sd, (struct sockaddr *)&addr, sizeof(addr)) <0)
 {
      sprintf(temp, "bind failed! errno:%d", WSAGetLastError());
   closesocket(sd);
      return -1;
 }
 if(hWnd && WSAAsyncSelect(sd, hWnd, WM_TCP, FD_ACCEPT) !=0)
    {
      sprintf(temp, "tcp_bind:WSAAsyncSelect failed!");
      closesocket(sd);
      return -2;
    }
    //sd_bind =sd;
    listen(sd, 5);
    return sd;
}

int CTcp::accept(int sd, int timeout)
{
  int sd_acc =-1;
  struct sockaddr_in sa;
  int len;
  /*unsigned long l;*/

  if(status(sd, "rw", timeout) <0)
    return -1;
  len =sizeof(sa);
  if((sd_acc =::accept(sd, (struct sockaddr *)&sa, &len)) <0)
    return -1;
  //sd_accept =sd_acc;
  /*  l =1;
    if(ioctlsocket(sd_acc, FIONBIO, &l) <0)
    {
      closesocket(sd);
      return -1;
    }*/
  return sd_acc;
}

int CTcp::connect(char *hostname, int port, int timeout, int f_noblock)
{
    struct hostent *hp;
    struct sockaddr_in addr;
    char temp[200];
    unsigned long ul;
    long l;
    int sd =-1, ret;
    time_t t1, t2;

    sd =-1;
 if((sd =::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) <0)
 {
  sprintf(temp, "socket failed! errno:%d", WSAGetLastError());
  return -1;
 }

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

    ul =inet_addr(hostname);
    if(ul ==0xffffffff)
    {
   if((hp =gethostbyname(hostname)) ==NULL)
   {
        sprintf(temp, "gethostbyname and inet_addr failed! errno:%d", WSAGetLastError());
     closesocket(sd);
        return -1;
      }
   memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
 }
    else  addr.sin_addr.s_addr=ul;

 addr.sin_family =AF_INET;
 addr.sin_port =htons((unsigned short)port);
    l =1;
    if(/*f_noblock && */ioctlsocket(sd, FIONBIO, (unsigned long *)&l) <0)
    {
      closesocket(sd);
      return -1;
    }
    /*if(setsockopt(sd, IPPROTO_TCP, TCP_NODELAY, (char *)&l, sizeof(l)) <0)
    {
      closesocket(sd);
      return -1;
    }*/
    time(&t1);
 int counter=0;
    while((ret =::connect(sd, (struct sockaddr *)&addr, sizeof(addr))) !=0)
    {
  
      time(&t2);
      if((t2 -t1) > timeout)
      {
        closesocket(sd);
        return -1;
      }
      peek_message();
      int err_no =WSAGetLastError();
   if(ret ==SOCKET_ERROR)
   {
    if(counter++>10)
    {
     Sleep(100);
     counter=0;
    }
    if(err_no ==WSAEISCONN) break;
   }
   else if(err_no ==WSAEWOULDBLOCK /*|| err_no ==WSAEINPROGRESS*/ || err_no ==WSAEALREADY)
   {
          continue;
   }
          else
   {
  closesocket(sd);
     return -1;
   }
 }
    if(status(sd, "we", timeout) <0)
    {
      sprintf(temp, "status:Á¬½Ó·þÎñÆ÷ʧ°Ü!/n¼ì²é·þÎñÆ÷¶Ë³ÌÐòÊÇ·ñÔËÐÐ/nÇÒÖ÷»úµØÖ·ÊÇ·ñ%s, ¶Ë¿ÚÊÇ·ñ%d/n"
                    "errno=%d",
            hostname, port, WSAGetLastError());
      closesocket(sd);
      return -1;
    }

    //sd_connect =sd;
    return sd;
}

int CTcp::connect2(char *bind_ip, char *hostname, int port, int timeout, int f_noblock)
{
    struct hostent *hp;
    struct sockaddr_in addr;
    char temp[200];
    unsigned long ul;
    long l;
    int sd =-1, ret;
    time_t t1, t2;

    sd =-1;
 if((sd =socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) <0)
 {
  sprintf(temp, "socket failed! errno:%d", WSAGetLastError());
  return -1;
 }

 if(bind_ip && *bind_ip)
 {
  memset(&addr, 0, sizeof(addr));
  addr.sin_family =AF_INET;
  ul =inet_addr(bind_ip);
  if(ul ==0xffffffff)
  {
   closesocket(sd);
   return -1;
  }
  else addr.sin_addr.s_addr=ul;

  if(::bind(sd, (struct sockaddr *)&addr, sizeof(addr)) <0)
  {
    sprintf(temp, "tcp_connect: bind failed! errno:%d", WSAGetLastError());
    closesocket(sd);
    return -1;
  }
 }

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

    ul =inet_addr(hostname);
    if(ul ==0xffffffff)
    {
   if((hp =gethostbyname(hostname)) ==NULL)
   {
        sprintf(temp, "gethostbyname and inet_addr failed! errno:%d", WSAGetLastError());
     closesocket(sd);
        return -1;
      }
   memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
 }
    else  addr.sin_addr.s_addr=ul;

 addr.sin_family =AF_INET;
 addr.sin_port =htons((unsigned short)port);
    l =1;
    if(/*f_noblock && */ioctlsocket(sd, FIONBIO, (unsigned long *)&l) <0)
    {
      closesocket(sd);
      return -1;
    }
    /*if(setsockopt(sd, IPPROTO_TCP, TCP_NODELAY, (char *)&l, sizeof(l)) <0)
    {
      closesocket(sd);
      return -1;
    }*/
    time(&t1);
 int counter=0;
    while((ret =::connect(sd, (struct sockaddr *)&addr, sizeof(addr))) !=0)
    {
      time(&t2);
      if((t2 -t1) > timeout)
      {
        closesocket(sd);
        return -1;
      }
      peek_message();
      int err_no =WSAGetLastError();
   if(ret ==SOCKET_ERROR)
   { 
    if(counter++>10)
    {
     Sleep(100);
     counter=0;
    }

    if(err_no ==WSAEISCONN) break;
   }
   else if(err_no ==WSAEWOULDBLOCK /*|| err_no ==WSAEINPROGRESS*/ || err_no ==WSAEALREADY)
   {
             continue;
   }
          else
   {
  closesocket(sd);
     return -1;
   }
 }
    if(status(sd, "we", timeout) <0)
    {
      sprintf(temp, "status:Á¬½Ó·þÎñÆ÷ʧ°Ü!/n¼ì²é·þÎñÆ÷¶Ë³ÌÐòÊÇ·ñÔËÐÐ/nÇÒÖ÷»úµØÖ·ÊÇ·ñ%s, ¶Ë¿ÚÊÇ·ñ%d/n"
                    "errno=%d",
            hostname, port, WSAGetLastError());
      closesocket(sd);
      return -1;
    }

    //sd_connect =sd;
    return sd;
}

 

void CTcp::disconnect(int sd)
{
  if(sd >0)
  {
    closesocket(sd);
    //if(sd ==sd_connect) sd_connect =-1;
    //if(sd ==sd_accept) sd_accept =-1;
    //if(sd ==sd_bind) sd_bind =-1;
  }
}

int CTcp::send(int sd, char *buf, int len, int timeout)
{
  int len1, len_send =0;
  time_t t1, t2;

  len_send =0;
  time(&t1);
  t2 =t1;
 int counter=0;
  while(len_send <len)
  {
    if(t2-t1 >timeout)
      return len_send;
    if(status(sd, "w", timeout-(t2-t1)) <0)
 {
      return len_send;
 }
    if((len1 =::send(sd, &buf[len_send], len-len_send, 0)) <=0)
    {
      if(len1 ==SOCKET_ERROR && GetLastError() ==WSAEWOULDBLOCK)
      {
        time(&t2);
  
  if(counter++>100)
    {
     Sleep(100);
     counter=0;
    }

        continue;
      }
      return len_send;
    }
    len_send +=len1;
    time(&t2);

  }

  return len_send;
}

int CTcp::recv(int sd, char *buf, int len, int timeout)
{
  int len1, len_recv;
  time_t t2, t1;

  len_recv =0;
  time(&t1);
  t2 =t1;

  int err =0;
  int counter=0;
  while(len_recv <len)
  {
    if(t2 -t1 >timeout)
 {
  WSASetLastError(err);
  return len_recv;
 }
    if(status(sd, "r", timeout-(t2-t1)) <0)
    {
  err =WSAGetLastError();
  //WriteStat("tcp_status err=%d", WSAGetLastError());
  WSASetLastError(err);
  return len_recv;
 }

 if((len1 =::recv(sd, &buf[len_recv], len-len_recv, 0)) <=0)
     {
  err =WSAGetLastError();
  //WriteStat("recv err=%d, len1=%d", err, len1);
       if(timeout ==0) break;
       if(len1 ==SOCKET_ERROR && err ==WSAEWOULDBLOCK)
       {
         time(&t2);

  if(counter++>100)
    {
     Sleep(100);
     counter=0;
    }

  continue;
       }
    WSASetLastError(err);
       return len_recv;
    }
    len_recv +=len1;
    time(&t2);
  }
  WSASetLastError(err);
  return len_recv;
}

int CTcp::gethostnamebyip(char *ip, char *host)
{
  struct hostent *hp;
  struct in_addr ul;

  host[0] =0;
  ul.S_un.S_addr =inet_addr(ip);
  if(ul.S_un.S_addr ==0xFFFFFFFF) return -1; // ip error or ip is hostname

  hp =gethostbyaddr((char *)&ul, 4, AF_INET);
  if(hp ==NULL) return -1;  // can not get hostname
  strcpy(host, hp->h_name);

  return 0;
}

int CTcp::get_local_ip(char *ip)
{
  struct hostent *hp;
  char host[50], *p;

  if(gethostname(host, sizeof(host)) <0) return -1;

  hp =gethostbyname(host);
  if(hp ==NULL) return -1;
  p =(char *)hp->h_addr;
  wsprintfA(ip, "%d.%d.%d.%d", (int)p[0]&0xFF, (int)p[1]&0xFF, (int)p[2]&0xFF, (int)p[3]&0xFF);

  return 0;
}

char* CTcp::get_remote_ip(int sd, char *ip)
{
  struct sockaddr_in addr_in;
  int len =sizeof(addr_in);
  char *p1;

  if(sd <0) return  NULL;
  if(getpeername(sd, (struct sockaddr *)&addr_in, &len) <0)
    return NULL;
  p1 =(char *)&addr_in.sin_addr;
  sprintf(ip, "%d.%d.%d.%d", ((int)p1[0]) &0xff, ((int)p1[1]) &0xff, (int)p1[2] &0xff, (int)p1[3]&0xff);
 
  return ip;
}

unsigned short CTcp::htons(unsigned short s)
{
 return ::htons(s);
}

unsigned short CTcp::ntohs(unsigned short s)
{
 return ::ntohs(s);
}

unsigned long int CTcp::htonl(unsigned long int l)
{
 return ::htonl(l);
}

unsigned long int CTcp::ntohl(unsigned long int l)
{
 return ::ntohl(l);
}

float CTcp::htonf(float f)
{
  unsigned char *p, p0, p1;

  if(htons(1) ==1) return f;
  p =(unsigned char *)&f;
  p0 =p[0];
  p1 =p[1];
  p[0] =p[3];
  p[3] =p0;
  p[1] =p[2];
  p[2] =p1;

  return f;
}

float CTcp::ntohf(float f)
{
  unsigned char *p, p0, p1;

  if(ntohs(1) ==1) return f;

  p =(unsigned char *)&f;
  p0 =p[0];
  p1 =p[1];
  p[0] =p[3];
  p[3] =p0;
  p[1] =p[2];
  p[2] =p1;
  return f;
}

double CTcp::htond(double d)
{
  unsigned char *p, p0, p1, p2, p3;

  if(htons(1) ==1) return d;

  p =(unsigned char *)&d;
  p0 =p[0];
  p1 =p[1];
  p2 =p[2];
  p3 =p[3];
  p[0] =p[7];
  p[7] =p0;
  p[1] =p[6];
  p[6] =p1;
  p[2] =p[5];
  p[5] =p2;
  p[3] =p[4];
  p[4] =p3;

  return d;
}

double CTcp::ntohd(double d)
{
  unsigned char *p, p0, p1, p2, p3;

  if(ntohs(1) ==1) return d;

  p =(unsigned char *)&d;
  p0 =p[0];
  p1 =p[1];
  p2 =p[2];
  p3 =p[3];
  p[0] =p[7];
  p[7] =p0;
  p[1] =p[6];
  p[6] =p1;
  p[2] =p[5];
  p[5] =p2;
  p[3] =p[4];
  p[4] =p3;

  return d;
}

unsigned __int64 CTcp::htonh(unsigned __int64 d)
{
  unsigned char *p, p0, p1, p2, p3;

  if(htons(1) ==1) return d;

  p =(unsigned char *)&d;
  p0 =p[0];
  p1 =p[1];
  p2 =p[2];
  p3 =p[3];
  p[0] =p[7];
  p[7] =p0;
  p[1] =p[6];
  p[6] =p1;
  p[2] =p[5];
  p[5] =p2;
  p[3] =p[4];
  p[4] =p3;

  return d;
}

unsigned __int64 CTcp::ntohh(unsigned __int64 d)
{
  unsigned char *p, p0, p1, p2, p3;

  if(ntohs(1) ==1) return d;

  p =(unsigned char *)&d;
  p0 =p[0];
  p1 =p[1];
  p2 =p[2];
  p3 =p[3];
  p[0] =p[7];
  p[7] =p0;
  p[1] =p[6];
  p[6] =p1;
  p[2] =p[5];
  p[5] =p2;
  p[3] =p[4];
  p[4] =p3;

  return d;
}

void CTcp::peek_message(void)
{
  MSG msg;

  if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }
}

int CTcp::bind_listen(int port,sockaddr_in& addr,long &err)
{

 int sock;
 

 
 sock = socket(AF_INET, SOCK_STREAM, 0);   // Create socket
 
 addr.sin_family = AF_INET;      // Address family Internet
 addr.sin_port = htons (port);     // Assign port 'port' to this socket
 addr.sin_addr.s_addr = htonl (INADDR_ANY);  // No destination
 
 if (::bind (sock, (LPSOCKADDR) &addr, sizeof (addr)) == SOCKET_ERROR)
 {
  closesocket (sock);
  err = WSAGetLastError ();
  return -1;
 }
 
 if (::listen (sock, 10) == SOCKET_ERROR)
 {
  closesocket (sock);
  err = WSAGetLastError ();
  return -1;
 }
 return sock;
}

void CTcp::close(int &sd)
{
 shutdown(sd,0);
 closesocket(sd);
 sd = INVALID_SOCKET;
}

阅读全文
0 0

相关文章推荐

img
取 消
img