/*
** 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;
}