📄 mproxy3.cpp
字号:
//*******************************************************************
//
// FILE: mproxy3.cpp
//
// AUTHOR: sam sha
//
// PROJECT: mproxysvr3
//
// COMPONENT: CMProxy3
//
// DATE: 23.06.2003
//
// COMMENTS: - 代理模块
//
//
//*******************************************************************
// Includes
// mproxy3.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "iodata.h"
#include "mproxy3.h"
#include <map>
#include "assert.h"
#include "greta/regexpr2.h"
using namespace std;
using namespace regex;
const int THREAD_MAXNUM = 10;//线程数目最大值
DWORD WINAPI MProxy3Thread(LPVOID pArgu);
//*******************************************************************
//
// FUNCTION: - CMProxy3
//
// RETURNS: -
//
// PARAMETERS: - int nListenPort 服务监听端口,const char * pAddr2 二级代理地址, int nPort2 二级代理端口
//
// COMMENTS: - 本程序为应用windows socket IO完成端口模型提供代理服务的原型设计.目前支持http的一级和二级代理。
// 可以指定其他的任何面向连接的二级代理。
//
//*******************************************************************
CMProxy3::CMProxy3(int nListenPort ,const char * pAddr2, int nPort2)
{
m_nListenPort = nListenPort;
m_Addr2[0] = 0; //是否有二级代理的条件
if (pAddr2)
{
strcpy(m_Addr2,pAddr2);
}
m_nPort2 = nPort2;
m_hThread = NULL;
m_nThreadState = STOP;
}
CMProxy3::~CMProxy3()
{
}
//*******************************************************************
//
// FUNCTION: -Start()
//
// RETURNS: -
//
// PARAMETERS: -
//
// COMMENTS: - 启动代理线程
//
//
//*******************************************************************
void CMProxy3::Start()
{
DWORD dwThreadID;
m_nThreadState = RUNNIG;
m_hThread = CreateThread(NULL,0,MProxy3Thread,(LPVOID)this,0,&dwThreadID);
if (m_hThread != NULL)
{
m_nThreadState = RUNNIG;
}
else
{
m_nThreadState = STOP;
}
}
//*******************************************************************
//
// FUNCTION: - Stop()
//
// RETURNS: -
//
// PARAMETERS: -
//
// COMMENTS: - 停止代理,代理会在下个请求进入后停止
//
//
//*******************************************************************
void CMProxy3::Stop()
{
m_nThreadState = STOP;
}
//*******************************************************************
//
// FUNCTION: - SafeClose
//
// RETURNS: -
//
// PARAMETERS: - LPWSAOVERLAPPEDEX lpOvlpEx 扩展的重叠IO模型
//
// COMMENTS: - 当要关闭socket连接时,要安全关闭一对soket
//
//
//*******************************************************************
void SafeClose(LPWSAOVERLAPPEDEX lpOvlpEx)
{
if ( lpOvlpEx->pPair != NULL )
{
SOCKET hPair = lpOvlpEx->hSocketPair;
lpOvlpEx->pPair->hSocketPair = INVALID_SOCKET - 1; //告诉伴侣我关了
lpOvlpEx->pPair->pPair = NULL;//告诉伴侣内存自己放了
closesocket(lpOvlpEx->hSocket); //close自己
GlobalFree(lpOvlpEx);//释放自己
shutdown(hPair,SD_BOTH);//把伴侣置位shutdown
}
else
{
closesocket(lpOvlpEx->hSocket); //close自己
GlobalFree(lpOvlpEx);//释放自己
}
}
//*******************************************************************
//
// FUNCTION: - MProxy3Thread
//
// RETURNS: -
//
// PARAMETERS: - LPVOID pArgu = CMProxy3 *pProxy3
//
// COMMENTS: - 服务主线程
//
//
//*******************************************************************
DWORD WINAPI MProxy3Thread(LPVOID pArgu)
{
CMProxy3 *pProxy3 = (CMProxy3 *)pArgu;
int nErr;
HANDLE hCompletionPort = CreateIoCompletionPort (
INVALID_HANDLE_VALUE,
NULL,
0,
0
);
if (!hCompletionPort)
{
//printf( "CompletionPort Create Failed\n");
return -1;
}
pProxy3->m_hCompletionPort = hCompletionPort;
SYSTEM_INFO si;
GetSystemInfo(&si);
DWORD i = 0;
for ( i = 0 ; i < THREAD_MAXNUM; i++ )
{
HANDLE hThread;
DWORD dwThreadID;
hThread = CreateThread(NULL,0,ServerWorkerThread,hCompletionPort,0,&dwThreadID);
//CloseHandle有无必要值得讨论,因为有时我们需要WaitForSingleObject(hThread,-1)来等待线程结束.
//
//CloseHandle(hThread);
}
SOCKADDR_IN localAddr;
SOCKET hListener;
hListener = WSASocket (AF_INET, SOCK_STREAM, 0,NULL,0,WSA_FLAG_OVERLAPPED);
if (hListener == INVALID_SOCKET)
{
//printf( "Socket Create Failed\n");
return -1;
}
//
// Bind our server to the agreed upon port number. See
// commdef.h for the actual port number.
//
ZeroMemory (&localAddr, sizeof (localAddr));
localAddr.sin_family = AF_INET;
localAddr.sin_port = htons (pProxy3->m_nListenPort);
localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
nErr = bind (hListener, (PSOCKADDR) & localAddr, sizeof (localAddr));
if (nErr == SOCKET_ERROR)
{
//printf( "Socket Bind Failed\n");
if (WSAGetLastError () == WSAEADDRINUSE)
//printf( "The port number may already be in use.\n");
return -1;
}
nErr = listen (hListener, 5);
if (nErr == SOCKET_ERROR)
{
//printf( "Socket Listen Failed\n");
return -1;
}
SOCKET hAcceptSocket;
while (pProxy3->m_nThreadState == CMProxy3::RUNNIG)
{
hAcceptSocket = WSAAccept(hListener,NULL,NULL,NULL,0);
//线程绝大多数是等候在WSAAccept
if (pProxy3->m_nThreadState != CMProxy3::RUNNIG)
{
closesocket(hAcceptSocket);
break;
}
/*
int TimeOut=0; //设置发送超时6秒
if(setsockopt(hAcceptSocket,SOL_SOCKET,SO_SNDTIMEO,(char *)&TimeOut,sizeof(TimeOut))!=SOCKET_ERROR){
////printf("client send time out = %d\n",TimeOut);
}
TimeOut=0;//设置接收超时6秒
if(::setsockopt(hAcceptSocket,SOL_SOCKET,SO_RCVTIMEO,(char *)&TimeOut,sizeof(TimeOut))!=SOCKET_ERROR){
////printf("client send time out = %d\n",TimeOut);
}
*/
WSAOVERLAPPEDEX * pAcceptOvl = (WSAOVERLAPPEDEX *) GlobalAlloc(GPTR,sizeof(WSAOVERLAPPEDEX));
if (pAcceptOvl == NULL)
{
closesocket(hAcceptSocket);
//printf("accept %d error...\n",hAcceptSocket);
continue;
}
//printf("=======================================Accept= %d \n",hAcceptSocket);
//assert(pAccept);
pAcceptOvl->pPair = NULL;
pAcceptOvl->WSABuf.buf = pAcceptOvl->Buffer;
pAcceptOvl->WSABuf.len = DATA_BUFSIZE;
pAcceptOvl->hSocket = hAcceptSocket;
pAcceptOvl->hSocketPair = INVALID_SOCKET;
pAcceptOvl->pProxy3 = pProxy3;
CreateIoCompletionPort((HANDLE)hAcceptSocket,hCompletionPort,(DWORD)hAcceptSocket,0);
//pAccept->Recv();
DWORD dwRecvBytes = 0,dwFlags = 0;
if ( WSARecv(hAcceptSocket,&pAcceptOvl->WSABuf,1,&dwRecvBytes,&dwFlags,(LPWSAOVERLAPPED)pAcceptOvl,NULL) == SOCKET_ERROR)
{
if ( WSAGetLastError() != WSA_IO_PENDING)
{
//printf("%d accept recv err = %d",hAcceptSocket,WSAGetLastError());
}
}
}
//**************************
//如果一定要强制终止以获得请求的连接,打开下面的代码
/*
for( i = 0 ; i < THREAD_MAXNUM ; i++)
{
PostQueuedCompletionStatus(hCompletionPort,0,0,0);
}
*/
//*****************************
CloseHandle(hCompletionPort);
return 0;
}
//*******************************************************************
//
// FUNCTION: - GetURL
//
// RETURNS: -
//
// PARAMETERS: - const string &strHeader , string & strProtocal, string &strAddress , int & nPort
//
// COMMENTS: - 从请求包中分析出,协议,服务器地址,端口号
//
//
//*******************************************************************
bool GetURL(const string &strHeader, string & strProtocal, string &strAddress , int & nPort);
//分析连接,直接代理
bool GetURL(const string &strHeader, string & strProtocal, string &strAddress , int & nPort)
{
// string strDebug = strHeader.substr(0,50);
// cout << strDebug << "\n\n";
// 应用Greta正则表达式解析
match_results results;
int nCount;
string str = strHeader;
string strPort;
rpattern pat("^.+ (.+)://(?:.+@)?([^/:]+)(?:.*:)?(\\d+)?");
match_results::backref_type br = pat.match( str, results );
if(!br.matched )
return false;
nCount = results.cbackrefs();
if (nCount == 4)
{
match_results::backref_type br1 = results.backref(1);
strProtocal = br1.str();
match_results::backref_type br2 = results.backref(2);
strAddress = br2.str();
match_results::backref_type br3 = results.backref(3);
strPort = br3.str();
nPort = atoi(strPort.c_str());
if (nPort == 0)
{
if (strProtocal =="http")
nPort = 80;
else
nPort = 21;
}
}
return true;
}
//*******************************************************************
//
// FUNCTION: - ServerWorkerThread
//
// RETURNS: -
//
// PARAMETERS: - LPVOID CompletionPortID
//
// COMMENTS: - 服务器工作线程
//
//
//*******************************************************************
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID)
{
HANDLE hCompletionPort = (HANDLE) CompletionPortID;
DWORD dwBytesTransferred = 0;
SOCKET hSocket;
LPWSAOVERLAPPEDEX lpOvlpEx;
int nErr;
while (1)
{
BOOL r = GetQueuedCompletionStatus(hCompletionPort,&dwBytesTransferred,(LPDWORD)&hSocket,(LPWSAOVERLAPPED *) &lpOvlpEx,INFINITE );
if (!r)
{
nErr = WSAGetLastError();
//printf("GetQueuedCompletionStatus = %d\n",nErr);
}
if (hSocket == 0 || lpOvlpEx == NULL)
break;
//printf("%d bytes transed...\n",dwBytesTransferred);
if (dwBytesTransferred == 0)
{
if (hSocket == lpOvlpEx->hSocket)
{
SafeClose(lpOvlpEx);
//printf(" .....................%d..........closed & freed........\n",hSocket);
}
continue;
}
if (hSocket == lpOvlpEx->hSocket)
{//
//printf("%d , recv = %d\n",hSocket,dwBytesTransferred);
if (lpOvlpEx->hSocketPair == INVALID_SOCKET)
{//第一个包请求,创建相关的socket
std::string strProtocal,strAddress;
int nPort;
CMProxy3 *pProxy = (CMProxy3 *)lpOvlpEx->pProxy3;
if (pProxy->m_Addr2[0] == 0)
{
char szHeader[DATA_BUFSIZE];
memcpy(szHeader,lpOvlpEx->Buffer,dwBytesTransferred);
szHeader[dwBytesTransferred] = 0;
if ( !GetURL(szHeader, strProtocal, strAddress , nPort))
{
closesocket(lpOvlpEx->hSocket);
GlobalFree(lpOvlpEx);
//printf("err url\n");
continue ;
}
}
else
{
strAddress = pProxy->m_Addr2;
nPort = pProxy->m_nPort2;
}
SOCKADDR_IN remoteAddr;
ZeroMemory (&remoteAddr, sizeof (remoteAddr));
remoteAddr.sin_family = AF_INET;
remoteAddr.sin_port = htons (nPort);
remoteAddr.sin_addr.s_addr = inet_addr(strAddress.c_str());
if(remoteAddr.sin_addr.s_addr == INADDR_NONE)
{
hostent * host = gethostbyname(strAddress.c_str());
if(host == NULL)
{
closesocket(lpOvlpEx->hSocket);
GlobalFree(lpOvlpEx);
//printf("err address\n");
continue;
}
memcpy(&remoteAddr.sin_addr,host->h_addr_list[0],host->h_length);
}
SOCKET hConnect;
hConnect = WSASocket (AF_INET, SOCK_STREAM, 0,NULL,0,WSA_FLAG_OVERLAPPED);
if (hConnect == INVALID_SOCKET)
{
//printf ("Socket Create Failed\n");
closesocket(lpOvlpEx->hSocket);
GlobalFree(lpOvlpEx);
continue;
}
int r = connect(hConnect,(PSOCKADDR)&remoteAddr,sizeof(remoteAddr));
if (r)
{
//printf ("Socket Connect Failed\n");
closesocket(hConnect);
closesocket(lpOvlpEx->hSocket);
GlobalFree(lpOvlpEx);
continue;
}
int iSize = sizeof(WSAOVERLAPPEDEX);
WSAOVERLAPPEDEX * pConnOvlEx = (WSAOVERLAPPEDEX *) GlobalAlloc(GPTR,sizeof(WSAOVERLAPPEDEX));
lpOvlpEx->pPair = pConnOvlEx;//互相
pConnOvlEx->pPair = lpOvlpEx;//指定
lpOvlpEx->hSocketPair = hConnect;
pConnOvlEx->hSocketPair = lpOvlpEx->hSocket;
pConnOvlEx->hSocket = hConnect;
pConnOvlEx->WSABuf.buf = pConnOvlEx->Buffer;
pConnOvlEx->WSABuf.len = DATA_BUFSIZE;
pConnOvlEx->pProxy3 = pConnOvlEx->pProxy3;
CreateIoCompletionPort((HANDLE)hConnect,hCompletionPort,(DWORD)hConnect,0);
/*
LINGER sl;
sl.l_onoff = 1;
sl.l_linger = 1;
setsockopt(pSocket->hSocket,SOL_SOCKET,SO_LINGER,(char *)&sl,sizeof(sl));
setsockopt(pSocket->pPair->hSocket,SOL_SOCKET,SO_LINGER,(char *)&sl,sizeof(sl));*/
//printf("==========================Connect = %d\n",hConnect);
DWORD dwRecvBytes = 0,dwFlags = 0;
ZeroMemory(pConnOvlEx,sizeof(WSAOVERLAPPED));
pConnOvlEx->WSABuf.len = DATA_BUFSIZE;
if ( WSARecv(hConnect,&pConnOvlEx->WSABuf,1,&dwRecvBytes,&dwFlags,(LPWSAOVERLAPPED)pConnOvlEx,NULL) == SOCKET_ERROR)
{
if ( WSAGetLastError() != WSA_IO_PENDING)
{
//printf("%d conn recv err = %d",pConnOvlEx->hSocket,WSAGetLastError());
SafeClose(lpOvlpEx);
continue;
}
}
}
//转发
DWORD dwReadBytes = 0,dwFlags = 0;
ZeroMemory(lpOvlpEx,sizeof(WSAOVERLAPPED));
lpOvlpEx->WSABuf.len = dwBytesTransferred;
if ( WSASend(lpOvlpEx->hSocketPair,&lpOvlpEx->WSABuf,1,&dwReadBytes,dwFlags,(LPWSAOVERLAPPED)lpOvlpEx,NULL) == SOCKET_ERROR)
{
if ( WSAGetLastError() != WSA_IO_PENDING)
{
//printf("%d Send err = %d",lpOvlpEx->hSocketPair,WSAGetLastError());
SafeClose(lpOvlpEx);
continue;
}
}
}
else if (hSocket == lpOvlpEx->hSocketPair)
{//数据发送完,转入接收状态
//printf("%d , send = %d\n",hSocket,dwBytesTransferred);
DWORD dwRecvBytes = 0,dwFlags = 0;
lpOvlpEx->WSABuf.len = DATA_BUFSIZE;
ZeroMemory(lpOvlpEx,sizeof(WSAOVERLAPPED));
if ( WSARecv(lpOvlpEx->hSocket,&lpOvlpEx->WSABuf,1,&dwRecvBytes,&dwFlags,(LPWSAOVERLAPPED)lpOvlpEx,NULL) == SOCKET_ERROR)
{
if ( WSAGetLastError() != WSA_IO_PENDING)
{
//printf("%d recv err = %d\n",lpOvlpEx->hSocket,WSAGetLastError());
SafeClose(lpOvlpEx);
continue;
}
}
}
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -