用VC++6.0编写Proxy服务器

    技术2022-05-11  70

    用VC++6.0编写Proxy服务器     本人在用Oicq聊天时,经常收到一些好友发给我的用文本符号描绘的图像,觉得好羡慕啊,于是一想何我们一般常用的Internet代理服务器是用微软的Proxy Server 2.0 。但我们可以自己动手编写一个简单、小型的Proxy Server 。下面介绍具体的实现方法。

    一. 原理 本程序的结构原理如下: 对于每一个用户的请求(Internet 请求,由浏览器发出),本程序将启动两个线程,一个把本地用户的请求数据发送到远程的Internet主机,另一个线程把远程主机的回应数据发送到本地请求用户。

    二. 主要函数     UserToProxyThread ( void * pParam ) :它是用来把本地用户请求数据发送到远程主机的,起服务器线程角色。当接到本地(局域网)用户的请求,它就启动另一个自身线程,以侦听别的用户的请求,并读出已接收到的请求数据,接着启动第二个线程ProxyToServer()(这个线程用来连接远程主机),当远程主机连接成功后,它把已读出的本地用户请求数据发送到远程主机。     ProxyToServer ( void * pParam) ,可以被当作是客户端服务,它把远程主机发送来的数据分发给本地请求用户。

    三. 开发运行环境     本程序是在VC++6.0环境下开发的,在Win95 和 WinNT4.0下运行正常。

    四. 详细代码

    #include "stdafx.h"#include <winsock2.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <iostream>

    using namespace std;

    #define HTTP  "http://"#define FTP  "ftp://"#define PROXYPORT 5001#define BUFSIZE  10240

    struct SocketPair{ SOCKET user_proxy; SOCKET proxy_server; bool IsUser_ProxyClosed; bool IsProxy_ServerClosec;};

    struct ProxyParam{ char  Address[256]; HANDLE  User_SvrOK; SocketPair* pPair;

     int  Port;};

    CWinApp  theApp;SOCKET  gListen_Socket;

    UINT ProxyToServer(LPVOID pParam);UINT UserToProxyThread(void* pParam);

    int StartServer(){ WSADATA  wsaData; sockaddr_in local; SOCKET  listen_socket;

     if (::WSAStartup(0x202, &wsaData) != 0) {  cout << "start up net work failed...." << endl;

      exit(0); }

     local.sin_addr.S_un.S_addr = INADDR_ANY; local.sin_family = AF_INET; local.sin_port = htons(PROXYPORT);

     listen_socket = socket(AF_INET, SOCK_STREAM, 0);

     if (listen_socket == INVALID_SOCKET) {  cout << "create socket failed..." << endl;

      return -1; }

     if (bind(liste_socket, (sockaddr*)&local, sizeof(local)) != 0) {  cout << "bind failed..." << endl;

      return -1; }

     if ((listen(listen_socket, 5)) != 0) {  cout << "listen failed..." << endl;

      return -1; }

     gListen_Socket = listen_socket;

     AfxBeginThread(UserToProxyThread, NULL);

     return 1;}

    int CloseServer(){ closesocket(gLiten_Socket);

     WSACleanup();

     return 1;}

    //分析接收到的字符,得到远程主机地址int GetAddressAndPort(char* str, char* address, int* port){ char buf[BUFSIZE] = "/0"; char command[512] = "/0"; char proto[128] = "/0"; char* p = NULL;

     int j = 0;

     cout << "Please input command" << endl; cin >> command;

     cout << "Please input buffer: " << endl; cin >> buf;

     cout << "Please input proto: " << endl; cin >> proto;

     p = strstr(buf, HTTP);

     if (p) {  p+=strlen(HTTP);  for(int i=0;i< strlen(p);i++)  {   if( *(p+i)=='/')   {    break;   }  }

      *(p+i)=0;  strcpy(address,p);    p=strstr(str,HTTP);    for(int j=0;j< i+strlen(HTTP);j++)  {   *(p+j)=' '; //去掉远程主机名: GET http://www.njust.edu.cn/HTTP1.1 == > GET / HTTP1.1  }    *port=80; //缺省的 http 端口  } else {//FTP, 不支持, 下面的代码可以省略.  p=strstr(buf,FTP);    if(!p)   {   return 0;  }

      p+=strlen(FTP);    for(int i=0;i< strlen(p);i++)  {   if( *(p+i)=='/')    {    break; //Get The Remote Host   }  }    *(p+i)=0;    for(j=0;j< strlen(p);j++)  {   if(*(p+j)==':')    {    *port=atoi(p+j+1); //Get The Port    *(p+j)=0;   }                        else    {    *port=21;    }  }    strcpy(address,p);  p=strstr(str,FTP);    for(j=0;j< i+strlen(FTP);j++)  {   *(p+j)=' ';   } }  return 1;

    }

    // 取到本地的数据,发往远程主机UINT UserToProxyThread(void *pParam){ char Buffer[BUFSIZE]; int Len; sockaddr_in from; SOCKET msg_socket; int fromlen,retval;  SocketPair SPair; ProxyParam ProxyP;  CWinThread *pChildThread;  fromlen = sizeof(from); msg_socket = accept(gListen_Socket,(struct sockaddr*)&from,&fromlen);

     AfxBeginThread(UserToProxyThread,pParam); //启动另一侦听.  if( msg_socket == INVALID_SOCKET) {  printf("/nError in accept ");     return -5; }

     //读客户的第一行数据 SPair.IsUser_ProxyClosed = FALSE; SPair.IsProxy_ServerClosed = TRUE; SPair.user_proxy = msg_socket;

     retval = recv(SPair.user_proxy,Buffer,sizeof(Buffer),0);  if(retval==SOCKET_ERROR) {  printf("/nError Recv");     if(SPair.IsUser_ProxyClosed == FALSE)  {   closesocket(SPair.user_proxy);      SPair.IsUser_ProxyClosed=TRUE;  } }  if (retval == 0) {  printf("Client Close connection/n");    if (SPair.IsUser_ProxyClosed == FALSE)  {   closesocket(SPair.user_proxy);      SPair.IsUser_ProxyClosed = TRUE;  } }  Len = retval;

    #ifdef _DEBUG

     Buffer[Len]=0; printf("/n Received %d bytes,data[%s]from client/n",retval,Buffer);#endif        SPair.IsUser_ProxyClosed=FALSE; SPair.IsProxy_ServerClosed=TRUE; SPair.user_proxy=msg_socket; ProxyP.pPair=&SPair; ProxyP.User_SvrOK=CreateEvent(NULL,TRUE,FALSE,NULL); GetAddressAndPort( Buffer,ProxyP.Address,&ProxyP.Port); pChildThread=AfxBeginThread(ProxyToServer,(LPVOID)&ProxyP); ::WaitForSingleObject(ProxyP.User_SvrOK,60000); //等待联结 ::CloseHandle(ProxyP.User_SvrOK);  while(SPair.IsProxy_ServerClosed ==FALSE && SPair.IsUser_ProxyClosed==FALSE) {   retval=send(SPair.proxy_server,Buffer,Len,0);  if(retval==SOCKET_ERROR)  {   printf("/n send() failed:error%d/n",WSAGetLastError());      if(SPair.IsProxy_ServerClosed==FALSE)   {    closesocket(SPair.proxy_server);    SPair.IsProxy_ServerClosed=TRUE;   }   continue;  }    retval=recv(SPair.user_proxy,Buffer,sizeof(Buffer),0);

      if(retval==SOCKET_ERROR)  {   printf("/nError Recv");       if(SPair.IsUser_ProxyClosed==FALSE)   {    closesocket(SPair.user_proxy);        SPair.IsUser_ProxyClosed=TRUE;   }      continue;  }    if(retval==0)  {   printf("Client Close connection/n");      if(SPair.IsUser_ProxyClosed==FALSE)   {    closesocket(SPair.user_proxy);        SPair.IsUser_ProxyClosed=TRUE;   }   break;  }    Len=retval;

    #ifdef _DEBUG    Buffer[Len]=0;  printf("/n Received %d bytes,data[%s]from client/n",retval,Buffer);#endif }  if(SPair.IsProxy_ServerClosed==FALSE) {  closesocket(SPair.proxy_server);   SPair.IsProxy_ServerClosed=TRUE; }  if(SPair.IsUser_ProxyClosed==FALSE) {  closesocket(SPair.user_proxy);    SPair.IsUser_ProxyClosed=TRUE; }  ::WaitForSingleObject(pChildThread- >m_hThread,20000); //Should check the   return value }

    // 读取远程主机数据,并发往本地客户机UINT ProxyToServer(LPVOID pParam){ ProxyParam * pPar=(ProxyParam*)pParam; char Buffer[BUFSIZE]; char *server_name= "localhost"; unsigned short port ; int retval,Len; unsigned int addr; int socket_type ; struct sockaddr_in server; struct hostent *hp; SOCKET conn_socket; socket_type = SOCK_STREAM; server_name = pPar- >Address;  port = pPar- >Port;

     if (isalpha(server_name[0]))  { /* server address is a name */  hp = gethostbyname(server_name); } else { /* Convert nnn.nnn address to a usable one */  addr = inet_addr(server_name);  hp = gethostbyaddr((char *)&addr,4,AF_INET); }

     if (hp == NULL )  {  fprintf(stderr,"Client: Cannot resolve address [%s]: Error %d/n",   server_name,WSAGetLastError());  ::SetEvent(pPar- >User_SvrOK);     return 0; }  // Copy the resolved information into the sockaddr_in structure

            memset(&server,0,sizeof(server)); memcpy(&(server.sin_addr),hp- >h_addr,hp- >h_length); server.sin_family = hp- >h_addrtype; server.sin_port = htons(port);  conn_socket = socket(AF_INET,socket_type,0); /* 打开一个 socket */  if (conn_socket < 0 )  {  fprintf(stderr,"Client: Error Opening socket: Error %d/n",WSAGetLastError());  pPar- >pPair- >IsProxy_ServerClosed=TRUE;  ::SetEvent(pPar- >User_SvrOK);     return -1; }

    #ifdef _DEBUG printf("Client connecting to: %s/n",hp- >h_name);#endif        if (connect(conn_socket,(struct sockaddr*)&server,sizeof(server))== SOCKET_ERROR)  {  fprintf(stderr,"connect() failed: %d/n",WSAGetLastError());    pPar->pPair->IsProxy_ServerClosed = TRUE;   ::SetEvent(pPar- >User_SvrOK);     return -1; }  pPar- >pPair- >proxy_server=conn_socket; pPar- >pPair- >IsProxy_ServerClosed=FALSE; ::SetEvent(pPar- >User_SvrOK);  // cook up a string to send  while(!pPar- >pPair- >IsProxy_ServerClosed &&!pPar- >pPair->IsUser_ProxyClosed) {  retval = recv(conn_socket,Buffer,sizeof (Buffer),0 );    if (retval == SOCKET_ERROR )   {   fprintf(stderr,"recv() failed: error %d/n",WSAGetLastError());      closesocket(conn_socket);      pPar->pPair->IsProxy_ServerClosed = TRUE;      break;  }    Len=retval;    if (retval == 0)   {   printf("Server closed connection/n");      closesocket(conn_socket);      pPar->pPair->IsProxy_ServerClosed=TRUE;      break;  }    retval = send(pPar- >pPair- >user_proxy,Buffer,Len,0);    if (retval == SOCKET_ERROR)   {   fprintf(stderr,"send() failed: error %d/n",WSAGetLastError());   closesocket(pPar- >pPair- >user_proxy);   pPar->pPair->IsUser_ProxyClosed=TRUE;      break;   }

    #ifdef _DEBUG   Buffer[Len]=0;   printf("Received %d bytes, data [%s] from server/n",retval,Buffer);#endif }  if(pPar- >pPair- >IsProxy_ServerClosed==FALSE) {  closesocket(pPar- >pPair- >proxy_server);  pPar->pPair- >IsProxy_ServerClosed=TRUE; }  if(pPar- >pPair- >IsUser_ProxyClosed==FALSE) {  closesocket(pPar- >pPair- >user_proxy);    pPar- >pPair- >IsUser_ProxyClosed=TRUE; }  return 1;} int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]){ int nRetCode = 0;  // 初始化SOCKET if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)) {  // 错误处理  cerr < < _T("Fatal Error: MFC initialization failed") < < endl;    nRetCode = 1; } else {  // 主程序开始.    StartServer();    } while(1)  {  if(getchar()=='q')   {   break;  } }

      CloseServer();

     return nRetCode;}

     


    最新回复(0)