码迷,mamicode.com
首页 > 其他好文 > 详细

HTTP转发小Demo

时间:2014-08-01 04:54:52      阅读:292      评论:0      收藏:0      [点我收藏+]

标签:http   socket   

工作中一个方案可行性预研写的小Demo,一晚上搞定的小程序.

主要功能是一个Http透明转发:

1.监听一个端口, 接收浏览器的连接请求.

2. 接收浏览器发出的请求数据, 将这些转发给一个指定的服务器.

3. 接收服务器的应答,将应答发送给浏览器.

代码都在一个文件中:

// httptranschannel.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "httptranschannel.h"
#include <iostream>
#include <string>

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

const int PORT_LOCAL = 8084;
//const char* SERVER_IP = "192.168.84.133";
//const int SERVER_PORT = 80;
const int PACKAGE_BUFFER_SIZE = 100*1024;	// 分包大小.

SOCKET g_listenSocket = INVALID_SOCKET;
SOCKET g_acceptSocket = INVALID_SOCKET;

SOCKET g_serverSocket = INVALID_SOCKET;	// 同服务器之间的连接Socket.

// 唯一的应用程序对象

CWinApp theApp;

using namespace std;

int InitSocket()
{
	// Initialize Winsock
	WSADATA wsaData;
	int iResult = 0;
	iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
	if (iResult != NO_ERROR) {
		wprintf(L"WSAStartup() failed with error: %d\n", iResult);
		return 1;
	}
	return 0;
}

int ListenSocket()
{
	if ( g_listenSocket == INVALID_SOCKET )
	{
		int iResult = 0;

		sockaddr_in service;

		//----------------------
		// Create a SOCKET for listening for incoming connection requests.
		g_listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
		if (g_listenSocket == INVALID_SOCKET) {
			wprintf(L"socket function failed with error: %ld\n", WSAGetLastError());
			WSACleanup();
			return 1;
		}
		//----------------------
		// The sockaddr_in structure specifies the address family,
		// IP address, and port for the socket that is being bound.
		service.sin_family = AF_INET;
		service.sin_addr.s_addr = ADDR_ANY; // inet_addr("127.0.0.1");
		service.sin_port = htons(PORT_LOCAL);

		iResult = bind(g_listenSocket, (SOCKADDR *) & service, sizeof (service));
		if (iResult == SOCKET_ERROR) {
			wprintf(L"bind function failed with error %d\n", WSAGetLastError());
			iResult = closesocket(g_listenSocket);
			if (iResult == SOCKET_ERROR)
				wprintf(L"closesocket function failed with error %d\n", WSAGetLastError());
			WSACleanup();
			return 1;
		}
		//----------------------
		// Listen for incoming connection requests 
		// on the created socket
		if (listen(g_listenSocket, SOMAXCONN) == SOCKET_ERROR)
			wprintf(L"listen function failed with error: %d\n", WSAGetLastError());

		wprintf(L"Listening on socket...\n");

		//----------------------
		// Create a SOCKET for accepting incoming requests.
		wprintf(L"Waiting for client to connect...\n");
	}
	
	//----------------------
	// Accept the connection.
	g_acceptSocket = accept(g_listenSocket, NULL, NULL);
	if (g_acceptSocket == INVALID_SOCKET) {
		wprintf(L"accept failed with error: %ld\n", WSAGetLastError());
		closesocket(g_listenSocket);
		WSACleanup();
		return 1;
	} else
		wprintf(L"Client connected.\n");

	//g_acceptSocket = accept(g_listenSocket, NULL, NULL);
	//if (g_acceptSocket == INVALID_SOCKET) {
	//	wprintf(L"accept failed with error: %ld\n", WSAGetLastError());
	//	closesocket(g_listenSocket);
	//	WSACleanup();
	//	return 1;
	//} else
	//	wprintf(L"Client connected.\n");

	return 0;
}

int DestroySocket()
{
	if ( INVALID_SOCKET != g_listenSocket )
	{
		int iResult = closesocket(g_listenSocket);
		if (iResult == SOCKET_ERROR) {
			wprintf(L"closesocket function failed with error %d\n", WSAGetLastError());
			WSACleanup();
			return 1;
		}
	}
	
	WSACleanup();
	return 0;
}

int ReceivFromSocket( SOCKET hSocket, char* pBuf, const int bufLen, int& dataLen, bool& disconnected )
{
	disconnected = false;

	fd_set fdSocket;        // 所有可用套节字集合
	FD_ZERO(&fdSocket);
	FD_SET( hSocket, &fdSocket);
	timeval tv;
	tv.tv_sec   =   0; 
	tv.tv_usec   =   0; 
	int nHasData = select( 1,&fdSocket, NULL, NULL, &tv) ; 
	if ( SOCKET_ERROR == nHasData )
	{
		cout << "ReceivFromSocket select fail! er: " << WSAGetLastError() << endl;

		disconnected = true;

		return -1;
	}
	else if( 1 == nHasData )
	{
		dataLen = recv( hSocket, pBuf, bufLen, 0 );

		// 返回0说明正常断开连接了.
		disconnected = (dataLen == 0);
		return 0;
	}
	else if( 0 == nHasData )
	{
		return 0;
	}
	else
	{
		cout << "ReceivFromSocket select return :" << nHasData << endl;
	}
	return -1;
}

int Connect2Server( const char* serverIp, const int serverPort )
{
	if ( g_serverSocket == INVALID_SOCKET )
	{
		sockaddr_in server;

		//----------------------
		// Create a SOCKET for listening for incoming connection requests.
		g_serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
		if (g_listenSocket == INVALID_SOCKET) {
			wprintf(L"socket function failed with error: %ld\n", WSAGetLastError());
			WSACleanup();
			return 1;
		}
		//----------------------
		// The sockaddr_in structure specifies the address family,
		// IP address, and port for the socket that is being bound.
		server.sin_family = AF_INET;
		server.sin_addr.s_addr = inet_addr( serverIp );
		server.sin_port = htons( serverPort );

		int result = connect( g_serverSocket, (SOCKADDR *)&server, sizeof( server ) );
		if ( 0 != result )
		{
			// 连接失败.
			cout << "Connect to server fail! ip: " << serverIp << " port: " << serverPort << " er: " << result << endl;

			// 销毁.
			closesocket( g_serverSocket );
			g_serverSocket = INVALID_SOCKET;
			return -1;
		}
	}
	return 0;
}

int Send2Socket( SOCKET hSock, const char* pBuf, const int dataLen )
{
	// 将数据发送给Server.
	int sendLen = 0;
	while( sendLen < dataLen )
	{
		int sendRet = send( hSock, pBuf + sendLen, dataLen - sendLen, 0 );
		if ( sendRet < 0 )
		{
			cout << "Send Data 2 server fail! ret: " << sendRet << " ec: " << WSAGetLastError() << endl;
			return -1;
		}
		else
		{
			sendLen += sendRet;
		}
	}
	return 0;
}

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
	int nRetCode = 0;

	HMODULE hModule = ::GetModuleHandle(NULL);

	if (hModule != NULL)
	{
		// 初始化 MFC 并在失败时显示错误
		if (!AfxWinInit(hModule, NULL, ::GetCommandLine(), 0))
		{
			// TODO: 更改错误代码以符合您的需要
			_tprintf(_T("错误: MFC 初始化失败\n"));
			nRetCode = 1;
		}
		else
		{
			string serverIp;
			int serverPort = 0;

			while( serverIp.empty() )
			{
				cout << "Please type in server ip: ";
				cin >> serverIp;
			}
			
			while( serverPort == 0 )
			{
				cout << "Please type in server port: ";
				cin >> serverPort;
			}

			// 初始化
			InitSocket();

			while(1)
			{
				int sleepTime = 50;
				if ( g_acceptSocket == INVALID_SOCKET )
				{
					// 监听端口,处理新连接.
					ListenSocket();
				}
				else
				{
					// 连接服务端
					Connect2Server( serverIp.c_str(), serverPort );

					// 新连接中,接收数据.
					char clientDataBuf[ PACKAGE_BUFFER_SIZE ] = {0};
					int dataLen = 0;
					bool disconnected = false;
					ReceivFromSocket( g_acceptSocket, clientDataBuf, sizeof( clientDataBuf ), dataLen, disconnected );

					if( disconnected )
					{
						cout << "accept socket disconnect!" << endl;
						closesocket( g_acceptSocket );
						g_acceptSocket = INVALID_SOCKET;
					}

					// 建立同服务端的新连接,将数据转发.
					if ( dataLen > 0 )
					{
						// 如果有数据, 就不等待. 否则等待.						
						sleepTime = 0;

						if ( g_serverSocket != INVALID_SOCKET )
						{
							Send2Socket( g_serverSocket, clientDataBuf, dataLen );
						}
					}
					

					// 接收服务端的数据,将数据发送给浏览器.
					if ( g_serverSocket != INVALID_SOCKET )
					{
						char serverDataBuf[ PACKAGE_BUFFER_SIZE ] = {0};
						int serverDataLen = 0;
						bool serverDisconnected = false;
						ReceivFromSocket( g_serverSocket, serverDataBuf, sizeof( serverDataBuf ), serverDataLen, serverDisconnected );

						if ( serverDataLen > 0 )
						{
							// 如果有数据, 就不等待. 否则等待.						
							sleepTime = 0;

							Send2Socket( g_acceptSocket, serverDataBuf, serverDataLen );
						}

						if ( serverDisconnected )
						{
							cout << "Server disconnect! " << endl;
							closesocket( g_serverSocket );
							g_serverSocket = INVALID_SOCKET;

							// 也和浏览器断链.
							closesocket( g_acceptSocket );
							g_acceptSocket = INVALID_SOCKET;
						}
					}

				}
				Sleep( sleepTime );
			}
		}
	}
	else
	{
		// TODO: 更改错误代码以符合您的需要
		_tprintf(_T("错误: GetModuleHandle 失败\n"));
		nRetCode = 1;
	}

	return nRetCode;
}

HTTP转发小Demo,布布扣,bubuko.com

HTTP转发小Demo

标签:http   socket   

原文地址:http://blog.csdn.net/thinkingl/article/details/38328597

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!