用VC++6.0编写Proxy服务器

用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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值