Simple Proxy Server C code implementation (Solaris)

Source: Internet
Author: User
Tags htons
/*
** Writing: Beyond Review
** Source: www.20cn. net
** Note: indicate the source of the post.
*/

# Include <stdio. h>
# Include <sys/types. h>
# Include <sys/socket. h>
# Include <netinet/in. h>
# Include <signal. h>
# Include <ARPA/inet. h>
# Include <netdb. h>
# Include <sys/Wait. H>
# Include <unistd. h>
# Include <string. h>
# Include <stdlib. h>
# Include <pthread. h>
# Include <sys/STAT. h>

Int m_mainid = 0; // master process ID
Int m_listensocket = 0; // listener socket
Char m_connectaddr [256] = {0}; // target address
Char m_connectport [256] = {0}; // target port

/*
** Function name: getlistensocket
** Function: generate a listening socket
** Input parameter: Port: Listener Port
** Output parameters: None
** Reference function: None
** Return value: Listener socket. If the value is 0, the socket fails to be generated, and the other value is the socket handle.
** Note: None
*/
Int getlistensocket (INT port)
{
Struct sockaddr_in m_lisaddr = {0 };
Int m_socket = 0;
Int m_addrlen = sizeof (struct sockaddr_in );

// Configure port information
M_lisaddr.sin_family = af_inet;
M_lisaddr.sin_port = htons (port );
M_lisaddr.sin_addr.s_addr = inaddr_any;

// Create a socket
If (m_socket = socket (af_inet, sock_stream, 0) <0)
{
// Failed to create socket
Return 0;
}

// Bind a socket
If (BIND (m_socket, (sockaddr *) & m_lisaddr, m_addrlen) <0)
{
// Failed to bind socket
Close (m_socket );
Return 0;
}

// Listener socket
If (Listen (m_socket, 5 ))
{
// Failed to listen for socket
Close (m_socket );
Return 0;
}

// The Listener socket is successfully generated.
Return m_socket;
}

/*
** Function name: getconnectsocket
** Function: generate a connection socket
** Input parameter: pserveraddr: Connection address: pserverport: Connection Port
** Output parameters: None
** Reference function: None
** Return value: connect to the socket. If the value is 0, the socket fails to be generated, and the other value is the socket handle.
** Note: None
*/
Int getconnectsocket (char * pserveraddr, char * pserverport)
{
Struct sockaddr_in m_serveraddr = {0 };
Int m_addrlen = sizeof (struct sockaddr_in );
Int m_socket = 0;

// Initialize the connection information
M_serveraddr.sin_addr.s_un.s_addr = inet_addr (pserveraddr );
M_serveraddr.sin_port = htons (atoi (pserverport ));
M_serveraddr.sin_family = af_inet;

// Create a sending socket
M_socket = socket (af_inet, sock_stream, 0 );
If (m_socket <= 0)
{
// Failed
Return NULL;
}

// Connect to the customer's computer
If (connect (m_socket, (sockaddr *) & m_serveraddr, m_addrlen) <0)
{
Close (m_socket );
Return NULL;
}

// Connection successful
Return m_socket;
}

/*
** Function name: transsocket
** Function: complete socket data forwarding
** Input parameter: m_sendsocket: sending socket m_recvsocket: receiving socket
** Output parameters: None
** Reference function: None
** Return value: None
** Note: Full Duplex is completed through reverse inversion.
*/
Void transsocket (INT m_sendsocket, int m_recvsocket)
{
Char m_buf [512*1024] = {0 };
Int ret = 0;
Fd_set readset;
Struct timeval TM = {0 };
TM. TV _sec = 3600*24;

Fd_zero (& readset );
Fd_set (m_recvsocket, & readset );

While (1)
{
If (select (m_recvsocket + 1, & readset, null, null, & TM)
<= 0 ))
{
// Error
Break;
}
If (! Fd_isset (m_recvsocket, & readset) continue;

Ret = Recv (m_recvsocket, m_buf, 512*1024 );
If (Ret <0)
{
// Error
Break;
}
Send (m_sendsocket, m_buf, RET, 0 );
}
Close (m_sendsocket );
Close (m_recvsocket );
}

/*
** Function name: sockettrans
** Function: the main function is used to forward data and start a new process.
** Input parameter: m_sendsocket: sending socket m_recvsocket: receiving socket
** Output parameters: None
** Reference function: None
** Return value: None
** Note: Full Duplex is completed through reverse inversion.
*/
Void sockettrans ()
{
Struct sockaddr_in m_workaddr = {0 };
Int m_191socket = 0;
Int m_147socket = 0;
Int m_workaddrlen = 0;

// Start task execution
While (1)
{
// Accept 147 of connections
M_workaddrlen = sizeof (struct sockaddr_in );
M_147socket = accept (m_listensocket,
(Sockaddr *) & m_workaddr, & m_workaddrlen );

// Check the validity of the socket
If (m_147socket <0) continue;

// Connect 191
M_191socket = getconnectsocket (m_connectaddr, m_connectport );
If (m_191socket = NULL)
{
Close (m_147socket );
Continue;
}

Int ret = fork ();
If (Ret <0)
{
// Failed to create a new process
Printf ("Fatal error, unable to create a new process! /N ");
Fflush (stdout );
Close (m_191socket );
Close (m_147socket );
Break;
}
Else if (ret = 0)
{
// Close the original Port
Close (m_listensocket );

// Create secondary sub-processes to prevent zombie Processes
Ret = fork ();
If (Ret <0)
{
Close (m_191socket );
Close (m_147socket );
_ Exit (0 );
}
Else if (ret = 0)
{
// Receiving process
Transsocket (m_191socket, m_147socket );
_ Exit (0 );
}
Ret = fork ();
If (Ret <0)
{
Close (m_191socket );
Close (m_147socket );
_ Exit (0 );
}
Else if (ret = 0)
{
// Sending Process
Transsocket (m_147socket, m_191socket );
_ Exit (0 );
}
Close (m_191socket );
Close (m_147socket );
_ Exit (0 );
}

// Wait until the sub-thread ends
Close (m_191socket );
Close (m_147socket );
Waitpid (Ret, null, 0 );
}
}

/*
** Function name: sig_usr
** Function: Process Signal Processing Function
** Input parameter: None
** Output parameters: None
** Reference function: None
** Return value: None
** Remarks: process the Process Termination event.
*/
Static void sig_usr (INT signo)
{
Close (m_listensocket );
If (m_mainid = getpid ())
Kill (0, sigkill );
Exit (0 );
}

Static void sig_ign (INT signo)
{
Fprintf (stderr, "signal % d catched, ignoring/N", signo );
}

Int daemon_init ()
{
Pid_t PID;
If (pid = fork () <0 ){
Return-1;
} Else if (PID! = 0 ){
Exit (0 );
}
Setsid ();
Umask (0 );
Return 0;
}

/*
** Function name: Main
** Function: Main process function
** Input parameter: None
** Output parameters: None
** Reference function: makefilepath, getmyinitinfo, sockettrans
** Return value: None
** Note: receives the main process function for the customer.
*/
Int main (INT argc, char * argv [])
{
// Check the validity of parameters
If (argc! = 4)
{
Printf ("Format: Destination Port of the local port/N ");
Fflush (stdout );
Return 0;
}

Daemon_init ();

// Register a signal event
Signal (sigterm, sig_usr );
Signal (SIGINT, sig_usr );
Signal (sigquit, sig_usr );
Signal (sigpipe, sig_ign );
Signal (sigalrm, sig_ign );
Signal (sigquit, sig_ign );
Signal (sigfpe, sig_ign );
Signal (sigill, sig_ign );
Signal (sigpipe, sig_ign );
Signal (SIGSEGV, sig_ign );
Signal (sigtrap, sig_ign );
Signal (sigtstp, sig_ign );

// Obtain parameters
Strcpy (m_connectaddr, argv [2]);
Strcpy (m_connectport, argv [3]);

// Obtain the listening socket
M_listensocket = getlistensocket (atoi (argv [1]);
If (m_listensocket = 0)
{
Printf ("listening port [% s] failed! /N ", argv [1]);
Fflush (stdout );
Return 0;
}

M_mainid = getpid ();
// Start the file receiving listening thread
Sockettrans ();
Close (m_listensocket );
Return 0;
}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.