有没有http转发程序?

BlackSnail 2004-12-26 09:09:10
我们的应用有这样的要求,http客户端(可能是IE或httpunit等可以收发标准http报文的应用程序),需要经过二个转发程序(转发器A、转发器B)访问Web服务器。在这里,不是http代理服务器,纯粹只是转发功能,因为http客户端访问的服务器地址是固定的。

我写了个转发程序,通过配置文件设置相关信息,比如转发器A的listen端口设置为IE的代理服务器端口,其目标地址和端口是转发器B的ip和port;而转发器B的listen端口为转发器A的目标端口,其目标地址和端口是Web服务器的ip和port。

应用主要是上传页面的下载和文件上传。在只使用一个转发器时,工作正常;当设置、运行两个转发器时,转发器B很快就出现“发送到Web服务器失败,错误码10053”的错误。请问,这是怎么回事,如何解决。

另外,哪里有较好的转发程序源码?这东西看起来简单,但要做得好还真困难,也许是我对socket机制理解得不深吧。

谢谢。
...全文
341 点赞 收藏 6
写回复
6 条回复
BlackSnail 2004年12月30日
OK,我试试,多谢了
回复 点赞
cugblue 2004年12月27日
用线程解决似乎不是很理想,我试过老是出问题。可以试一下完成端口什么的。
回复 点赞
cugblue 2004年12月27日
// Read data from remote and send data to local
UINT ProxyToServer(LPVOID pParam)
{
SocketPair * pPar=(SocketPair*)pParam;
char Buffer[BUFSIZE];
// char log[15000];
int retval,Len;
struct sockaddr_in server;
SOCKET conn_socket;



server.sin_family=AF_INET;
//代理服务器的地址和端口
server.sin_port=htons(80);
server.sin_addr.s_addr=inet_addr("202.113.49.22");

conn_socket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); /* Open a socket */
if (conn_socket <0 ) {
fprintf(stderr,"Client: Error Opening socket: Error %d\n",
WSAGetLastError());
pPar->IsProxy_ServerClosed=TRUE;
::SetEvent(pPar->User_SvrOK);
return -1;
}


if (connect(conn_socket,(struct sockaddr*)&server,sizeof(server))
== SOCKET_ERROR) {
fprintf(stderr,"connect() failed: %d\n",WSAGetLastError());
pPar->IsProxy_ServerClosed=TRUE;
::SetEvent(pPar->User_SvrOK);
return -1;
}
pPar->proxy_server=conn_socket;
pPar->IsProxy_ServerClosed=FALSE;
::SetEvent(pPar->User_SvrOK);
// cook up a string to send
while(!pPar->IsProxy_ServerClosed &&!pPar->IsUser_ProxyClosed)
{
retval = recv(conn_socket,Buffer,sizeof (Buffer),0 );
if (retval == SOCKET_ERROR ) {
// pPar->cs.Lock();
printf("\nErrorcode=%d, Recv from server,ThreadID=%d\n",WSAGetLastError(),GetCurrentThreadId());
// pPar->cs.Unlock();
closesocket(conn_socket);
pPar->IsProxy_ServerClosed=TRUE;
break;
}
Len=retval;
if (retval == 0) { //对方已关闭
// pPar->cs.Lock();
printf("\nServer Close connection,ThreadID=%d",GetCurrentThreadId());
// pPar->cs.Unlock();
closesocket(conn_socket);
pPar->IsProxy_ServerClosed=TRUE;
break;
}

retval = send(pPar->user_proxy,Buffer,Len,0);
if (retval == SOCKET_ERROR) {
// pPar->cs.Lock();
printf("\nErrorcode=%d, Send to client,ThreadID=%d\n",WSAGetLastError(),GetCurrentThreadId());
// pPar->cs.Unlock();
closesocket(pPar->user_proxy);
pPar->IsUser_ProxyClosed=TRUE;
break;
}
#ifdef _DEBUG
if (Len==-1) Buffer[0]=0;
else Buffer[Len]=0;
// pPar->cs.Lock();
printf("Received %d bytes, data [%s] from server\n",retval,Buffer);
// pPar->cs.Unlock();
#endif
}
if(pPar->IsProxy_ServerClosed==FALSE)
{
closesocket(pPar->proxy_server);
pPar->IsProxy_ServerClosed=TRUE;
}
if(pPar->IsUser_ProxyClosed==FALSE)
{closesocket(pPar->user_proxy);
pPar->IsUser_ProxyClosed=TRUE;
}
return 1;
}
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;

// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
cerr << _T("Fatal Error: MFC initialization failed") << endl;
nRetCode = 1;
}
else
{
// TODO: code your application's behavior here.
StartServer();
while(1)
if(getchar()=='q') break;
CloseServer();
}
return nRetCode;
}
回复 点赞
cugblue 2004年12月27日
下面代码是利用多线程转发,问题是一方断开连接,另一方不是很同步。
这个代码也是我修改别人的,浅尝辄止,没能解决问题,不知对你有用否。
#include "stdafx.h"
#include "Proxy.h"
#include <winsock2.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <afxmt.h>
//#include <afx.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// The one and only application object

#define PROXYPORT 5060 //Proxy Listen Port
#define BUFSIZE 10240 //Buffer size

CWinApp theApp;
using namespace std;
UINT ProxyToServer(LPVOID pParam);
UINT UserToProxyThread(void *pParam);

struct SocketPair{
SOCKET user_proxy; //socket : local machine to proxy server
SOCKET proxy_server; //socket : proxy sever to remote server
BOOL IsUser_ProxyClosed; // status of local machine to proxy server
BOOL IsProxy_ServerClosed; // status of proxy server to remote server
HANDLE User_SvrOK; // status of setup connection between proxy server and remote server
CCriticalSection cs;
};

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

if(::WSAStartup(0x202,&wsaData)!=0)
{printf("\nError in Startup session.\n");WSACleanup();return -1;};

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

listen_socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(listen_socket==INVALID_SOCKET)
{printf("\nError in New a Socket.");WSACleanup();return -2;}
if(::bind(listen_socket,(sockaddr *)&local,sizeof(local))!=0)
{printf("\n Errorcode %d in Binding socket.",WSAGetLastError());WSACleanup();return -3; };
if(::listen(listen_socket,5)!=0)
{printf("\n Error in Listen."); WSACleanup(); return -4;}
gListen_Socket=listen_socket;

AfxBeginThread(UserToProxyThread,NULL); //Start accept function
return 1;
}

int CloseServer()
{
closesocket(gListen_Socket);
WSACleanup();
return 1;
}


// Setup chanel and read data from local , send data to remote
UINT UserToProxyThread(void *pParam)
{
char Buffer[BUFSIZE];
// char log[15000];
int Len;
sockaddr_in from;
SOCKET msg_socket;
int fromlen,retval;
SocketPair SPair;

CWinThread *pChildThread;
fromlen=sizeof(from);
msg_socket=accept(gListen_Socket,(struct sockaddr*)&from,&fromlen);
AfxBeginThread(UserToProxyThread,pParam); //Start another thread to listen.
if( msg_socket==INVALID_SOCKET)
{ printf( "\nError in accept "); return -5;}

//recieve the first line of client

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("Errorcode=%d Recv from client,ThreadID=%d",WSAGetLastError(),GetCurrentThreadId());
if(SPair.IsUser_ProxyClosed==FALSE)
{closesocket(SPair.user_proxy);
SPair.IsUser_ProxyClosed=TRUE;
}
}
if(retval==0)
{printf("\nClient Close connection,ThreadID=%d",GetCurrentThreadId());
if(SPair.IsUser_ProxyClosed==FALSE)
{closesocket(SPair.user_proxy);
SPair.IsUser_ProxyClosed=TRUE;
}
}
Len=retval;
#ifdef _DEBUG
if (Len==-1) Buffer[0]=0;
else Buffer[Len]=0;
//SPair.cs.Lock();
printf("\n Received %d bytes,data[\n%s\n]from client\n",retval,Buffer);
//SPair.cs.Unlock();


#endif
//
SPair.IsUser_ProxyClosed=FALSE;
SPair.IsProxy_ServerClosed=TRUE;
SPair.user_proxy=msg_socket;
SPair.User_SvrOK=CreateEvent(NULL,TRUE,FALSE,NULL);

pChildThread=AfxBeginThread(ProxyToServer,(LPVOID)&SPair);
::WaitForSingleObject(SPair.User_SvrOK,60000); //Wait for connection between proxy and remote server
::CloseHandle(SPair.User_SvrOK);

while(SPair.IsProxy_ServerClosed ==FALSE && SPair.IsUser_ProxyClosed==FALSE)
{
retval=send(SPair.proxy_server,Buffer,Len,0);

if(retval==SOCKET_ERROR)
{// SPair.cs.Lock();
printf("\nErrorcode=%d, Send to server,ThreadID=%d\n",WSAGetLastError(),GetCurrentThreadId());
//SPair.cs.Unlock();


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)
{
//SPair.cs.Lock();
printf("\nErrorcode=%d, Recv from client,ThreadID=%d\n",WSAGetLastError(),GetCurrentThreadId());
//SPair.cs.Unlock();
if(SPair.IsUser_ProxyClosed==FALSE)
{closesocket(SPair.user_proxy);
SPair.IsUser_ProxyClosed=TRUE;
}
continue;
}
if(retval==0)
{//SPair.cs.Lock();
printf("\nClient Close connection,ThreadID=%d",GetCurrentThreadId());
//SPair.cs.Unlock();
if(SPair.IsUser_ProxyClosed==FALSE)
{closesocket(SPair.user_proxy);
SPair.IsUser_ProxyClosed=TRUE;
}
break;
}
Len=retval;
#ifdef _DEBUG
if (Len==-1) Buffer[0]=0;
else Buffer[Len]=0;
// SPair.cs.Lock();
printf("\n Received %d bytes,data[\n%s\n]from client\n",retval,Buffer);
// SPair.cs.Unlock();
#endif

} //End While

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,INFINITE); //Should check the reture value
return 0;
}
回复 点赞
cugblue 2004年12月27日
不能,完成端口是windows独有。
回复 点赞
BlackSnail 2004年12月27日
Linux平台能支持完成端口吗?
回复 点赞
发动态
发帖子
网络编程
创建于2007-09-28

7880

社区成员

6.4w+

社区内容

VC/MFC 网络编程
社区公告
暂无公告