15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


Пример простейшего прокси

Автор: KMiNT21

Пример простейшего каскадирующего прокси под Win32. Правильнее было бы назвать это чем-то вроде "port mapper" или "port redirect". Чтобы было легче разбираться в коде, я даю лишь скелет программы, убрав все лишние строки.

Если Вы хотите прочесть мою статью "Пишем прокси сервер" с подробнейшим комментированием этого исходника или "Синхронные и асинхронные сокеты в Windows", то идете на сервере www.uinc.ru в раздел статьи - (www.uinc.ru/articles). Первая - будет там в ближайшие дни (а возможно, уже там присутствует), а врорая уже есть. Все комментарии шлите на mail.

 

Далее представлен сам исходник:

#include 


// НАСТРОЙКА  ПАРАМЕТРОВ
#define IN_PORT     1111
#define OUT_IP      "192.168.0.89"
#define OUT_PORT    80
#define MAX_DATA    100
#define MAXCONN 1000
#define IDE_MSG 110
#define WM_ASYNC_CLIENTEVENT  WM_USER+1
#define WM_ASYNC_PROXYEVENT WM_USER+10

LRESULT CALLBACK MainWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);
void ConnectToProxy(SOCKET);


SOCKET hListenSockTCP   = INVALID_SOCKET;
SOCKADDR_IN     myaddrTCP,proxyaddrTCP;
char buf[MAX_DATA];
SOCKET sockets[MAXCONN];
HWND hwndMain;

int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrevInst,LPSTR szCmdLine,int nCmdShow)
{
  WSADATA stWSADataTCPIP;
  if(WSAStartup(0x0101, &stWSADataTCPIP)) 
                      MessageBox(0,"WSAStartup error !","NET ERROR!!!",0); 

  ZeroMemory(sockets,sizeof(sockets));

  WNDCLASS wc;
  memset(&wc,0,sizeof(WNDCLASS));
  wc.style = CS_HREDRAW|CS_VREDRAW |CS_DBLCLKS ;
  wc.lpfnWndProc = (WNDPROC)MainWndProc;
  wc.hInstance = hInst;
  wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  wc.lpszClassName = "CProxy";
  wc.lpszMenuName = NULL;
  wc.hCursor = LoadCursor(NULL,IDC_ARROW);
  wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);
  if (!RegisterClass(&wc)) return 0;

  hwndMain=CreateWindow("CProxy","ProxyExample", WS_MINIMIZEBOX|
                         WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_MAXIMIZEBOX|
                         WS_CAPTION|WS_BORDER|WS_SYSMENU|WS_THICKFRAME,
                         CW_USEDEFAULT,0,CW_USEDEFAULT,0, NULL, NULL, hInst, NULL);
  ShowWindow(hwndMain,SW_SHOW);
  

  hListenSockTCP = socket (AF_INET,SOCK_STREAM,0);
  myaddrTCP.sin_family = AF_INET;
  myaddrTCP.sin_addr.s_addr = htonl (INADDR_ANY);
  myaddrTCP.sin_port = htons (IN_PORT);
  if(bind(hListenSockTCP,(LPSOCKADDR)&myaddrTCP, sizeof(struct sockaddr))) { 
           MessageBox(hwndMain,"This port in use!","BIND TCP ERROR!!!",0);
  } 
  if (listen (hListenSockTCP, 5)) MessageBox(hwndMain,"listen error!","ERROR!!!",0);
  WSAAsyncSelect (hListenSockTCP,hwndMain,WM_ASYNC_CLIENTEVENT,
                                              FD_ACCEPT|FD_READ|FD_CLOSE);
  
  
  MSG  msg;
  while(GetMessage(&msg,NULL,0,0))
  {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }
  return msg.wParam;

  return 0;
}



LRESULT CALLBACK MainWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
   WORD WSAEvent;
   int i;
   DWORD currentsock;

  switch (msg)
  {

  case WM_COMMAND:
    break;

  case WM_DESTROY:
    PostQuitMessage(0);  // 10xu4yourtime
    break;


  case WM_ASYNC_CLIENTEVENT: // Сообщения про события сокетов, подключенных к клиенту.
    currentsock = wParam;
    WSAEvent = WSAGETSELECTEVENT (lParam);
    switch (WSAEvent)
    {
      case FD_CLOSE :
           shutdown(sockets[currentsock],1);
           closesocket(currentsock);
           return 0;

      case FD_READ:
           // ПЕРЕНАПРАВЛЕНИЕ ДАННЫХ (redirect). Берем от клиента, посылаем на сервер.
           i=recv(currentsock, buf, MAX_DATA, 0);
                 send(sockets[currentsock],  buf, i, 0); // и отправляем...
           return 0;

      case FD_ACCEPT:
           ConnectToProxy(accept(hListenSockTCP,NULL,NULL));
           return 0;
      }
      break;

  case WM_ASYNC_PROXYEVENT:
       // Найдем соответствующий дескриптор.
       for (i=0;i<MAXCONN;i++)
       if (sockets[i] == wParam) { currentsock=i; break; }
       WSAEvent = WSAGETSELECTEVENT (lParam);
       switch (WSAEvent)
           {
         // Произошло подключение к удаленному хосту
         case FD_CONNECT :
           i=WSAGETSELECTERROR(lParam);
           if (i!=0)
           {
             shutdown(currentsock,1);
             closesocket(sockets[currentsock]);
             sockets[currentsock]=INVALID_SOCKET;
           }
        return 0;
                   
                   
                // Сервер нас отрубает ...
                case FD_CLOSE :
                           shutdown(currentsock,1);
                           closesocket(sockets[currentsock]);
                           sockets[currentsock]=INVALID_SOCKET;
                           return 0;

                        // Перенаправление данных клиенту
          case FD_READ:
         i=recv(sockets[currentsock], buf, MAX_DATA, 0);
                     send(currentsock,buf, i, 0);
                     return 0;
            }
                break;
  }
  return DefWindowProc(hwnd,msg,wParam,lParam);
}







// Connect to PROXY

void ConnectToProxy(SOCKET nofsock)
{
  SOCKADDR_IN rmaddr;
  rmaddr.sin_family = AF_INET;
  rmaddr.sin_addr.s_addr = inet_addr(OUT_IP);
  rmaddr.sin_port = htons (OUT_PORT);

  sockets[nofsock] = socket (AF_INET,SOCK_STREAM,0);
  if(INVALID_SOCKET == sockets[nofsock])
                 MessageBox(0,"INVALID_SOCKET","ERROR!!!",0);

  WSAAsyncSelect (sockets[nofsock],hwndMain,WM_ASYNC_PROXYEVENT,
                                              FD_CONNECT|FD_READ|FD_CLOSE);
  
  connect (sockets[nofsock], (struct sockaddr *)&rmaddr,sizeof(rmaddr));
  
  return;  // Connect OK
}

 

Скачать исходник - 3 Kb