One. principle
The structural principles of this program are as follows:
For each user's request (INTERNET request, the browser is issued), this program will start two threads, a request for local users
Data is sent to a remote Internet host, and another thread sends a response data of the remote host to the local requesting user.
two. Main function
UserToproxythread (Void * PParam): It is used to send local users to request data to remote hosts, from server line
Cheng role. When receiving the request from the local (LAN) user, it starts another own thread to listen to the request of other users, and read the connected
Request data received, then start the second thread proxyToServer () (this thread is used to connect the remote host), when the remote host is connected
After work, it sends the read local user request data to the remote host.
ProxyToServer (Void * PPARAM) can be used as a client service, which distributes the data sent by the remote host to the local
Ask for users.
three. Develop a running environment
This program is developed in the VC 6.0 environment, running in Win95 and WinNT4.0.
four. Detailed code
#include "stdafx.h"
#include "proxy.h"
#include
#include
#include
#include
#ifdef _Debug
#define new debug_new
#undef this_file
Static char this_file [] = __file__;
#ENDIF
#define http "http://"
#define ftp "ftp: //"
#define proxyport 5001 // proxy port
#define bufsize 10240 // buffer size
CWINAPPPP;
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 Service to Remote Host
Bool isuser_proxyclosed; // Local machine to Proxy server status
Bool isproxy_serverclosed; // proxy service to remote host status
}
Struct proxyparam {
CHAR Address [256]; // Remote host address
Handle user_svrok; // proxy server to the connection status of the remote host
SocketPair * ppair; / / Maintain a set of socket pointers
Int port; // Used to join the port of the remote host
}; File: // This structure is used to exchange information with the remote host.
Socket Glisten_Socket; file: // Socket used to listen to.
Int StartServer () // Start service
{
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 = incoddr_any;
Local.sin_port = htons (proxyport);
Listen_Socket = Socket (AF_INET, SOCK_STREAM, 0);
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 error in binding socket."); 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 listening
Return 1;
}
Int CloseServer () // Close service
{
CloseSocket (GLISTEN_SOCKET);
WSACLEANUP ();
Return 1;
}
File: // Analyze the received characters to get the remote host address
Int getaddressandport (Char * Str, Char * Address, INT * Port)
{
Char buf [buffsize], command [512], proto [128], * p;
Int J;
SSCANF (STR, "% S% S% S", Command, BUF, Proto;
P = strstr (buf, http);
// http
IF (p)
{
P = Strlen (http);
For (int i = 0; i IF (* (p i) == `/`) Break; * (p i) = 0; STRCPY (Address, P); P = str, http); For (int J = 0; j
* (p j) = ``; // remove the remote host name: get http://www.njust.edu.cn/ Http1.1 ==> Get / http1.1 * Port = 80; // Default HTTP port } Else {// ftp, does not support, the following code can be omitted. P = strstr (buf, ftp); IF (! p) Return 0; P = Strlen (FTP); For (int i = 0; i IF (* (p i) == `/`) Break; // Get The Remote Host * (p i) = 0; For (j = 0; j IF (* (p j) == `:`) {* port = atoi (p j 1); // Get the port * (p j) = 0; } Else * Port = 21; STRCPY (Address, P); P = str, ftp); For (j = 0; j
* (p j) = ``; } Return 1; } / / Take local data and send it to the remote host Uint UserToproxythread (void * pparam) { Char buffer [buffs]; 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, (strunt socketdr *) & from, & fromlen AfxBeginThread (UserToproxythread, PParam); // Start another listener. IF (msg_socket == invalid_socket) {Printf ("/ NERROR in Accept"); Return-5;} // read the first line of data from the customer 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", return, 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); GetDressandport (Buffer, Proxyp.address, & Proxyp.Port); PChildthread = AFXBEGINTHREAD (PROXYTOSERVER, (LPVOID) & proxyp); :: waitforsingleObject (proxyp.user_svrok, 60000); // Waiting for joint :: 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", return, buffer; #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, 20000); // Should Check The Return Value Return 0; } / / Read remote host data and send it to the local client Uint proxytoserver (lpvoid pparam) { ProxyParam * PPAR = (ProxyParam *) PPARAM; Char buffer [buffs]; 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 {/ * converat 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 inform the 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); / * Open a 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 (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; // Initialize Socket IF (! Afxwininit (:: getModuleHandle (Null), NULL, :: getcommandline (), 0)) { // Error handling CERR <<_t ("Fatal Error: MFC Initialization Failed") < NRETCODE = 1; } Else { // The main program begins. StartServer (); While (1) IF (getchar () == `q`) Break; CloseServer (); } Return nretcode; }