Use fork and socket sample in php. Read the sample using fork and socket in php, recently, I have encountered a big problem. this code has made it difficult for everyone to test the non-dynamic AP function in their home Database, he only provides the ability to map external IPs to a specific IP address in Nat, but cannot specify a Port map to a specific internal IP address. However, I have "> <recently, I have met this code is a big question. let's take a test.
The non-dynamic AP function of Home Inns is not very good. he only provides the ability to map the real external IP addresses to an IP address in Nat.
A port map cannot be specified to an internal IP address.
However, I have mapped external IP addresses to the internal
LinuxServer,
However, I want to use a VNC internal from the external to the internal server.
WindowsE-MapReduce.
So this program is released.
The principle is as follows:
This program will open a Port on the Linux Server as the Listen action.
When the external server accesses this Port, the program will launch another internal server to the internal Windows VNC.
Copy the external packets to the original VNC snapshot, and then copy the original VNC snapshot back to the external Port.
Program example:
#! /Usr/bin/php-q
$ IP = '1970. 168.1.1 '; // IP address of Windows computer
$ Port = '000000'; // Port used by VNC
$ ServerPort = '000000'; // Port used outside of the Linux Server
$ RemoteSocket = false; // The Socket connecting to VNC
FunctionSignalFunction ($ Signal)
{
// This is the principal information processing function of the main Process.
Global $ PID; // PID of Child Process
Switch ($ Signal)
{
CaseSIGTRAP:
CaseSIGTERM:
// Receive the Signal of the end program
If ($ PID)
{
// Send a SIGTERM response to the Child and tell the Child to quickly end the response.
Posix_kill ($ PID, SIGTERM );
// Wait until the Child Process ends to avoid zombie
Pcntl_wait ($ Status );
}
// Close the Socket opened by the main Process
DestroySocket ();
Exit (0); // end the main Process
Break;
CaseSIGCHLD:
/*
When Child Process is terminated, Child will send a SIGCHLD distributed packet to Parrent
When Parrent receives SIGCHLD, it will know that Child Process has been finished. we should do some
End Action */
Unset ($ PID); // clear $ PID, indicating that Child Process has ended
Pcntl_wait ($ Status); // avoid Zombie
Break;
Default:
}
}
FunctionChildSignalFunction ($ Signal)
{
// This is the information processing function of Child Process.
Switch ($ Signal)
{
CaseSIGTRAP:
CaseSIGTERM:
// Child Process receives the end message
DestroySocket (); // disables Socket
Exit (0); // end the Child Process
Default:
}
}
FunctionProcessSocket ($ ConnectedServerSocket)
{
// Child Process Socket processing function
// $ ConnectedServerSocket-> external Socket
Global $ ServerSocket, $ RemoteSocket, $ IP, $ Port;
$ ServerSocket = $ ConnectedServerSocket;
Declare (ticks = 1); // This line must be added, otherwise there is no way to set the parameter processing function.
// Set the processing amount of interest
If (! Pcntl_signal (SIGTERM, "ChildSignalFunction") return;
If (! Pcntl_signal (SIGTRAP, "ChildSignalFunction") return;
// Create a Socket connecting to VNC
$ RemoteSocket = socket_create (AF_INET, SOCK_STREAM, SOL_TCP );
// Route requests to the internal VNC
@ $ RemoteConnected = socket_connect ($ RemoteSocket, $ IP, $ Port );
If (! $ RemoteConnected) return; // cannot route to the end of VNC
// Set Socket processing to Nonblock to avoid program blocking
If (! Socket_set_nonblock ($ RemoteSocket) return;
If (! Socket_set_nonblock ($ ServerSocket) return;
While (true)
{
// Here we use the pooling method to obtain information
$ NoRecvData = false; // This variable is used to determine whether the external response has received the data.
$ NoRemoteRecvData = false; // This variable is used to determine whether the VNC snapshot has received data.
@ $ RecvData = socket_read ($ ServerSocket, 4096, PHP_BINARY_READ );
// Retrieve 4096 bytes of data from external locations
@ $ RemoteRecvData = socket_read ($ RemoteSocket, 4096, PHP_BINARY_READ );
// Obtain 4096 bytes of data from vnc.
If ($ RemoteRecvData = '')
{
// VNC zookeeper in progress, which should end
Echo "Remote Connection Close \ n ";
Return;
}
If ($ RemoteRecvData = false)
{
/*
Since we are using the nonblobk mode
In this case, vnc does not have any information available for retrieval.
*/
$ NoRemoteRecvData = true;
// Clear the Last Errror
Socket_clear_error ($ RemoteSocket );
}
If ($ RecvData = '')
{
// An external token is being processed. The result is
Echo "Client Connection Close \ n ";
Return;
}
If ($ RecvData = false)
{
/*
Since we are using the nonblobk mode
In this case, the external store does not have any information available for retrieval.
*/
$ NoRecvData = true;
// Clear the Last Errror
Socket_clear_error ($ ServerSocket );
}
If ($ NoRecvData & $ NoRemoteRecvData)
{
// If no information is available for both the external region and the VNC region,
// Let the program sleep for 0.1 seconds to avoid using CPU resources for a long period of time
Usleep (100000 );
// After waking up, the callback will be used as a pooling action to retrieve the socket
Continue;
}
// Recv Data
If (! $ NoRecvData)
{
// Obtain the information from the external website
While (true)
{
// Send the externally distributed information to the VNC region
@ $ WriteLen = socket_write ($ RemoteSocket, $ RecvData );
If ($ WriteLen === false)
{
// Due to the online shopping problem, there is currently no way to import data.
// First sleep for 0.1 seconds and then wait for a while.
Usleep (100000 );
Continue;
}
If ($ WriteLen = 0)
{
// The program is being executed on the terminal. The program is closed.
Echo "Remote Write Connection Close \ n ";
Return;
}
// When the information retrieved from the external store has been completely sent to the VNC, it will be in the middle of the loop.
If ($ WriteLen = strlen ($ RecvData) break;
// If the data cannot be sent at one time, it must be split into a batch delivery until all the data is sent
$ RecvData = substr ($ RecvData, $ WriteLen );
}
}
If (! $ NoRemoteRecvData)
{
// This is the information obtained from the VNC website, and then sent back to the external website.
// The principles are similar to those described above.
While (true)
{
@ $ WriteLen = socket_write ($ ServerSocket, $ RemoteRecvData );
If ($ WriteLen === false)
{
Usleep (100000 );
Continue;
}
If ($ WriteLen = 0)
{
Echo "Remote Write Connection Close \ n ";
Return;
}
If ($ WriteLen = strlen ($ RemoteRecvData) break;
$ RemoteRecvData = substr ($ RemoteRecvData, $ WriteLen );
}
}
}
}
FunctionDestroySocket ()
{
// Use the Socket that has been opened
Global $ ServerSocket, $ RemoteSocket;
If ($ RemoteSocket)
{
// If you have enabled VNC authentication
// You must shutdown the Socket before closing the Socket. Otherwise, the other party will not know that you have already been connected.
@ Socket_shutdown ($ RemoteSocket, 2 );
Socket_clear_error ($ RemoteSocket );
// Disable Socket
Socket_close ($ RemoteSocket );
}
// Disable external zookeeper
@ Socket_shutdown ($ ServerSocket, 2 );
Socket_clear_error ($ ServerSocket );
Socket_close ($ ServerSocket );
}
// This is the start of the entire program. The program starts starting from this line.
// The fork line is first written here.
$ PID = pcntl_fork ();
If ($ PID =-1) die ("cocould not fork ");
// If $ PID is not 0, this is Parrent Process.
// $ PID is Child Process
// This is the end of the Parrent Process itself, making Child a Daemon.
If ($ PID) die ("Daemon PID: $ PID \ n ");
// Starting from this point, the Daemon mode is running
// Convert the current Process and terminal into the daemon mode
If (! Posix_setsid () die ("cocould not detach from terminal \ n ");
// Set the message handling function of daemon
Declare (ticks = 1 );
If (! Pcntl_signal (SIGTERM, "SignalFunction") die ("Error !!! \ N ");
If (! Pcntl_signal (SIGTRAP, "SignalFunction") die ("Error !!! \ N ");
If (! Pcntl_signal (SIGCHLD, "SignalFunction") die ("Error !!! \ N ");
// Create an external Socket
$ ServerSocket = socket_create (AF_INET, SOCK_STREAM, SOL_TCP );
// Set the IP address, Port, and IP address of the external listener to 0, indicating the IP address of all interfaces.
If (! Socket_bind ($ ServerSocket, 0, $ ServerPort) die ("Cannot Bind Socket! \ N ");
// Start listening Port
If (! Socket_listen ($ ServerSocket) die ("Cannot Listen! \ N ");
// Set Socket to nonblock mode
If (! Socket_set_nonblock ($ ServerSocket) die ("Cannot Set Server Socket to Block! \ N ");
// Clear the $ PID variable, indicating that no Child Process exists.
Unset ($ PID );
While (true)
{
// Enter the pooling mode, and check whether there is any progress in the pipeline every 1 second.
Sleep (1 );
// Check whether there is any progress
@ $ ConnectedServerSocket = socket_accept ($ ServerSocket );
If ($ ConnectedServerSocket! = False)
{
// Someone else uploads it.
// A Child Process is used to Process the processing worker.
$ PID = pcntl_fork ();
If ($ PID =-1) die ("cocould not fork ");
If ($ PID) continue; // This is the daemon process, and zookeeper goes back to listen.
// Start with Child Process
// Response data in the Socket
ProcessSocket ($ ConnectedServerSocket );
// After processing the Socket, end the Socket
DestroySocket ();
// End with Child Process
Exit (0 );
}
}
?>