一个简单的QQ聊天代码

来源:互联网 发布:javascript 打印堆栈 编辑:程序博客网 时间:2024/05/01 18:38

#include <winsock2.h>
#include <windows.h>
#include <iostream.h>
#pragma  comment (lib,"ws2_32")

#define  locport       8000
#define  gatport       11282
#define  maxsize     40*1024

struct   sockaddr_in sin[2][4]={{0}};
SOCKET   sock[2][2]={{0}},slisten=INVALID_SOCKET;
BOOL     local;
int      addrlen=sizeof(struct sockaddr_in);

void start()
{
 cout<<"            ---------------------------------------------------/n";
 cout<<"              ||                                           || /n";
 cout<<"              ||              QQtcp  (TCP转发)             || /n";
 cout<<"              ||                                           || /n";
 cout<<"            ---------------------------------------------------"<<endl;
}

void usage()
{
    cout<<"/nUsage:/r/n/tQQtcp  -l[-g]  ip  port"<<endl;
 cout<<"/tQQtcp  -h"<<endl;
 cout<<"Example:/r/n";
 cout<<"/tQQtcp  -l  127.0.0.1       11282"<<endl;
 cout<<"/tQQtcp  -l  192.168.0.1     11282"<<endl;
 cout<<"/tQQtcp  -g  61.144.238.156  8000"<<endl;
 cout<<"Attention:"<<endl;
 cout<<"/t选项 -l :  运行于本机上,ip填网关地址,port必须为11282(网关监听端口);"<<endl;
 cout<<"/t           QQ客户端所填服务器地址为127.0.0.1,端口为8000(本地监听端口);"<<endl;
    cout<<"/t选项 -g :  运行于网关上,ip填腾讯服务器地址,port为腾讯服务器端口;"<<endl;
 cout<<"/t选项 -h :  查阅扩展功能及相关帮助文件。"<<endl;
}

DWORD WINAPI t2u(LPVOID param)
{
 UNREFERENCED_PARAMETER(param);
 fd_set   fdread,fdwrite;
 int      ret,ileft,idx,istbcs=0,iret;
 char     msgrecv[maxsize]={0},msgsend[maxsize]={0};

 while(1)
 {
  FD_ZERO(&fdread);
  FD_ZERO(&fdwrite);
  FD_SET(sock[1][0],&fdread);
  FD_SET(sock[1][1],&fdwrite);
  if((ret=select(0,&fdread,&fdwrite,NULL,NULL))==SOCKET_ERROR)
  {
   cout<<"/nThread 1 select error: "<<GetLastError()<<endl;
   break;
  }
  if(ret>0)
  {
   if(FD_ISSET(sock[1][0],&fdread))
   {
    iret=recv(sock[1][0],msgrecv,sizeof(msgrecv),0);
    if(iret==SOCKET_ERROR)
    {
     cout<<"Thread 1 recv error: "<<GetLastError()<<endl;
     break;
    }
    else if(iret==0)
    {
                    break;
    }
    cout<<"/nThread 1 TCP Recv "<<iret<<" bytes from "<<inet_ntoa(sin[1][0].sin_addr)<<endl;
    memcpy(msgsend+istbcs,msgrecv,iret);
    istbcs+=iret;
    memset(msgrecv,0,sizeof(msgrecv));
   }
   else if(FD_ISSET(sock[1][1],&fdwrite))
   {
    ileft=istbcs;
    idx=0;

    while(ileft>0)
    {
          if(sin[1][3].sin_port==htons(0))
     {
      cout<<"sin[1][3].sin_port==0"<<endl;
          break;
     }
     iret=sendto(sock[1][1],&msgsend[idx],ileft,0,(struct sockaddr *)&sin[1][3],addrlen);
     if(iret==SOCKET_ERROR)
     {
      cout<<"Thread 1 sendto error: "<<GetLastError()<<endl;
      break;
     }
     else if(iret==0)
     {
      break;
     }
     cout<<"Thread 1 UDP Send "<<iret<<" bytes  to  "<<inet_ntoa(sin[1][3].sin_addr)<<endl;
     ileft-=iret;
     idx+=iret;
    }
    memset(msgsend,0,sizeof(msgsend));
    istbcs=0;
   }
  }
  Sleep(50);
 }
 return 0;
}


DWORD WINAPI u2t(LPVOID param)
{
 UNREFERENCED_PARAMETER(param);
    fd_set  fdread,fdwrite;
 struct  sockaddr_in  tempr;
 int     ret,iret,idx,ileft,istbcs=0;
    char    msgrecv[maxsize]={0},msgsend[maxsize]={0};

 while(1)
 {
  FD_ZERO(&fdread);
  FD_ZERO(&fdwrite);
  FD_SET(sock[0][0],&fdread);
  FD_SET(sock[0][1],&fdwrite);     
  if((ret=select(0,&fdread,&fdwrite,NULL,NULL))==SOCKET_ERROR)
  {
   cout<<"/nThread 0 select error: "<<GetLastError()<<endl;
   break;
  }
  if(ret>0)
  {
   if(FD_ISSET(sock[0][0],&fdread))
   {

    iret=recvfrom(sock[0][0],msgrecv,sizeof(msgrecv),0,(struct sockaddr *)&tempr,&addrlen);
    if(iret==SOCKET_ERROR)
    {
     cout<<"Thread 0 recvfrom error: "<<GetLastError()<<endl;
     break;
    }
    else if(iret==0)
    {
     break;
    }

    if(sin[0][0].sin_port==htons(0))
    {
     sin[0][0].sin_port=tempr.sin_port;
     sin[1][3].sin_port=tempr.sin_port;
    }
    else if(sin[0][0].sin_port!=tempr.sin_port)
     break;

    cout<<"/nThread 0 UDP recv "<<iret<<" bytes from "<<inet_ntoa(sin[0][0].sin_addr)<<endl;
    memcpy(msgsend+istbcs,msgrecv,iret);
    istbcs+=iret;
    memset(msgrecv,0,sizeof(msgrecv));
   }
   else if(FD_ISSET(sock[0][1],&fdwrite))
   {
    ileft=istbcs;
    idx=0;
    while(ileft>0)
    {
        iret=send(sock[0][1],&msgsend[idx],ileft,0);
        if(iret==SOCKET_ERROR)
     {
         cout<<"Thread 0 send error: "<<GetLastError()<<endl;
         break;
     }
        else if(iret==0)
     {
      break;
     }
     cout<<"Thread 0 TCP send "<<iret<<" bytes  to  "<<inet_ntoa(sin[0][3].sin_addr)<<endl;
     ileft-=iret;
     idx+=iret;
    }
    memset(msgsend,0,sizeof(msgsend));
    istbcs=0;
   }
  }
  Sleep(50);
 }
 return 0;
}


int main(int argc,char *argv[])
{
 WSADATA  wsa;
 int      ret,log;
    HANDLE   threads[2];
    DWORD    threadid[2];

 system("cls.exe");
 start();
 if(WSAStartup(MAKEWORD(2,2),&wsa)!=0)
 {
  cout<<"WSAStartup error: "<<GetLastError()<<endl;
  return -1;
 }
 if(argc==2 && !strcmp(argv[1],"-h"))
 {
  ShellExecute(NULL,"open","help.txt",NULL,NULL,SW_SHOWMAXIMIZED);
  return 0;
 }
 else if(argc!=4)
 {
  usage();
  return -1;
 }
 else if(!strcmp(argv[1],"-l"))
 {
  local=true;
 }
 else if(!strcmp(argv[1],"-g"))
  local=false;
 else
 {
  usage();
  return -1;
 }

 if(local)
 {
  sin[0][0].sin_addr.s_addr=inet_addr("127.0.0.1");         
  sin[0][0].sin_family=AF_INET;
        sin[0][0].sin_port=htons(0);

  sin[0][1].sin_addr.s_addr=htonl(INADDR_ANY);
  sin[0][1].sin_family=AF_INET;
  sin[0][1].sin_port=htons(locport);

  sin[0][2].sin_addr.s_addr=htonl(INADDR_ANY);
  sin[0][2].sin_family=AF_INET;
  sin[0][2].sin_port=htons(locport);

  sin[0][3].sin_addr.s_addr=inet_addr(argv[2]);
  sin[0][3].sin_family=AF_INET;
  sin[0][3].sin_port=htons(atoi(argv[3]));
 }
 else
 {
  sin[0][3].sin_addr.s_addr=htonl(0);      
  sin[0][3].sin_family=AF_INET;
        sin[0][3].sin_port=htons(0);

  sin[0][2].sin_addr.s_addr=htonl(INADDR_ANY);
  sin[0][2].sin_family=AF_INET;
  sin[0][2].sin_port=htons(gatport);

  sin[0][1].sin_addr.s_addr=htonl(INADDR_ANY);
  sin[0][1].sin_family=AF_INET;
  sin[0][1].sin_port=htons(gatport);

  sin[0][0].sin_addr.s_addr=inet_addr(argv[2]);
  sin[0][0].sin_family=AF_INET;
  sin[0][0].sin_port=htons(atoi(argv[3]));
 }
 for(int i=0;i<4;i++)
  sin[1][i]=sin[0][3-i];

 if((sock[0][0]=socket(AF_INET,SOCK_DGRAM,0))==INVALID_SOCKET)
 {
  cout<<"Socket sock[0][0] error: "<<GetLastError()<<endl;
  return -1;
 }
 if(bind(sock[0][0],(struct sockaddr *)&sin[0][1],addrlen)==SOCKET_ERROR)
 {
  cout<<"Bind sock[0][0] error: "<<GetLastError()<<endl;
  return -1;
 }
 sock[1][1]=sock[0][0];

 if(!local)
 {
     if((slisten=socket(AF_INET,SOCK_STREAM,0))==INVALID_SOCKET)
  {
      cout<<"Socket slisten error: "<<GetLastError()<<endl;
      return -1;
  }

     if(bind(slisten,(struct sockaddr *)&sin[0][2],addrlen)==SOCKET_ERROR)
  {
      cout<<"Bind slisten error: "<<GetLastError()<<endl;
      return -1;
  }

  if(listen(slisten,1)==SOCKET_ERROR)
  {
   cout<<"Listen slisten error: "<<GetLastError()<<endl;
   return -1;
  }
 }
  
 cout<<"正常工作中..."<<endl<<endl;

 while(1)
 {
     if(local)
  {
        sock[0][1]=socket(AF_INET,SOCK_STREAM,0);
         sock[1][0]=sock[0][1];

      while(1)
   {
             if(connect(sock[0][1],(struct sockaddr *)&sin[0][3],addrlen)==SOCKET_ERROR)
    {
        if(GetLastError()==10061)
         cout<<"Remote computer's target port isn't active/r"<<flush;
        Sleep(2000);
              continue;
    }
                sin[0][0].sin_port=htons(0);
    sin[1][3].sin_port=htons(0);
        cout<<"/nConnect Successfully"<<endl;
        break;
   }
  }
     else
  {
       if((sock[1][0]=accept(slisten,(struct sockaddr *)&sin[1][0],&addrlen))==SOCKET_ERROR)
   {
    cout<<"Accept error: "<<GetLastError()<<endl;
       break;
   }
      sock[0][1]=sock[1][0];
   sin[0][3].sin_addr=sin[1][0].sin_addr;
      cout<<"Accept Successfully"<<endl;
  }


     threads[0]=CreateThread(NULL,0,u2t,(LPVOID)0,0,&threadid[0]);
     threads[1]=CreateThread(NULL,0,t2u,(LPVOID)1,0,&threadid[1]);
  
     ret=WaitForMultipleObjects(2,threads,false,INFINITE);
     if(ret==WAIT_FAILED)
  {
      cout<<"WaitForMultipleObjects error: "<<GetLastError()<<endl;
       return -1;
  }
  log=ret-WAIT_OBJECT_0;
  if(log>=0 && log<2)
  {
       for(int j=0;j<2;j++)
   {
       if(threads[i]!=NULL)
            CloseHandle(threads[j]);
       for(int k=0;k<2;k++)
    {
        if(sock[j][k]!=INVALID_SOCKET && j!=k)
     {
      if(sock[j][k]!=INVALID_SOCKET)
                 closesocket(sock[j][k]);
     }
    }
   }
  }
  else
   break;
 }
 if(slisten!=INVALID_SOCKET)
     closesocket(slisten);
 WSACleanup();
 return 0;
}
 

 

 


 

原创粉丝点击