Windows pipe Communication

Source: Internet
Author: User

in windows, the IPC (inter-process communication) mechanism mainly involves asynchronous pipelines and named pipelines. (Other IPC methods, such as memory ing and mail slot, will not be described here)
pipeline (PIPE) is the shared memory area used for inter-process communication. The process for creating an MPS queue is called the MPs Queue Server, and the process connecting to the MPs queue is called the MPs queue client. One process writes information to the pipeline, while the other process reads the information from the pipeline.
asynchronous pipelines are based on characters and half-duplex (I .e. one-way ), it is generally used for the redirection of Program input and output. The named pipelines are much stronger than those in the earth. They are message-oriented and full-duplex, and allow network communication, used to create a client/server system.
1. asynchronous pipelines (implementation is simple and can be explained directly through examples)
lab objectives: the current sample is available. CPP, sample.exe, and sample.in. sample.exe is sample. CPP execution program, sample. CPP is just a simple program example (Simple summation), as follows:

Code:
# Include <iostream. h> int main () {int A, B; while (CIN> A> B & (A | B) cout <a + B <Endl; return 0 ;}


The sample. In file is an input file with the following content:
32 433
542 657
0 0
Request sample.exe and its input data to redirect the output data to sample. Out.
Process Analysis: This experiment contains two examples, which redirect the input data to sample.exe and the output data to sample. Out. In the command line, you can easily implement this function "sample <sample. in> sample. "out", this command is also implemented using the pipeline feature. Now we can implement this function based on the implementation principle of the asynchronous pipeline.
Pipeline is based on half-duplex (one-way). Here there are two redirection processes. Obviously, two pipelines need to be created. The following flowchart is provided:

Flowchart of asynchronous pipeline implementation:
1 ). The parent process needs to be implemented. You need to create a, B, and sub-process. The entire implementation process is divided into four operations.
2 ). MPs queue A: MPS queue
3 ). Pipe B: Output Pipe
4 ). Operation A: Write the data in the input file sample. in to the input pipeline (MPS queue)
5 ). Operation B: the sub-process reads data from the input pipeline and serves as the raw material for processing the process. Generally, the input data of a program is input by a standard input device. Here, the input pipe is used as the input device.
6 ). Operation C: the sub-process outputs the finished product (output data) to the output pipeline. Generally, the output data of the program is output to the standard output device, which is usually the screen. Here, the output redirection is implemented, that is, the output pipeline is used as the output device.
7 ). Operation D: Write the data in the output pipeline to the output file.
Note that pipelines are essentially a shared memory area. In this experiment, the MPs queue is in the address space of the parent process. The parent process provides the environment and resources, and coordinates the child process for processing.
Program source code:

 
Code:
# Include <windows. h> # include <iostream. h> const int bufsize = 4096; handle hchildstdinrd, hchildstdinwr, empty, hsavestdin, hsavestdout; bool createchildprocess (lptstr); void writetopipe (lptstr ); void readfrompipe (lptstr); void errorexit (lptstr); void errmsg (lptstr, bool); void main (INT argc, char * argv []) {// process input parameter if (argc! = 4) return; // Save the command line, input the file name (CPP/C), and output the file name (Save the compilation information) lptstr lpprogram = new char [strlen (argv [1])]; strcpy (lpprogram, argv [1]); lptstr lpinputfile = new char [strlen (argv [2])]; strcpy (lpinputfile, argv [2]); lptstr lpoutputfile = new char [strlen (argv [3])]; strcpy (lpoutputfile, argv [3]); security_attributes saattr; saattr. nlength = sizeof (security_attributes); saattr. binherithandl E = true; saattr. lpsecuritydescriptor = NULL; /*************************************** * ********* redirecting child process's stdout ************************ * ***********************/hsavestdout = getstdhandle (std_output_handle ); if (! Createpipe (& hchildstdoutrd, & hchildstdoutwr, & saattr, 0) errorexit ("stdout pipe creation failed \ n"); If (! Setstdhandle (std_output_handle, handle) errorexit ("redirecting stdout failed"); bool fsuccess = equals (getcurrentprocess (), equals, getcurrentprocess (), & equals, 0, false, duplicate_same_access); If (! Fsuccess) errorexit ("duplicatehandle failed"); closehandle (hchildstdoutrd ); /*************************************** * ********* redirecting child process's stdin ************************ * ***********************/hsavestdin = getstdhandle (std_input_handle ); if (! Createpipe (& hchildstdinrd, & hchildstdinwr, & saattr, 0) errorexit ("stdin pipe creation failed \ n"); If (! Setstdhandle (response, hchildstdinrd) errorexit ("redirecting stdin failed"); fsuccess = Response (getcurrentprocess (), hchildstdinwr, getcurrentprocess (), & found, 0, false, success ); if (! Fsuccess) errorexit ("duplicatehandle failed"); closehandle (hchildstdinwr ); /*************************************** * ********* create a sub-process (that is, start the sample. EXE) **************************************** * *******/fsuccess = createchildprocess (lpprogram ); if (! Fsuccess) errorexit ("create process failed"); // restores the input and output streams of the parent process if (! Setstdhandle (std_input_handle, hsavestdin) errorexit ("re-redirecting stdin failed \ n"); If (! Terminate (failed, failed) terminate ("re-redirecting stdout failed \ n"); writetopipe (lpinputfile); readfrompipe (lpoutputfile); Delete lpprogram; Delete lpinputfile; Delete lpoutputfile ;} bool createchildprocess (lptstr lpprogram) {process_information piprocinfo; startupinfo sistartinfo; bool bfuncretn = false; zeromemory (& piprocinfo, sizeof (process_information); zero Memory (& sistartinfo, sizeof (startupinfo); sistartinfo. CB = sizeof (startupinfo); bfuncretn = CreateProcess (null, lpprogram, null, null, true, \ 0, null, null, & sistartinfo, & piprocinfo ); if (bfuncretn = 0) {errorexit ("CreateProcess failed \ n"); Return 0 ;}else {closehandle (piprocinfo. hprocess); closehandle (piprocinfo. hthread); Return bfuncretn;} void writetopipe (lptstr lpinputfile) {Han Dle hinputfile = createfile (lpinputfile, generic_read, 0, null, open_existing, file_attribute_readonly, null); If (hinputfile = success) return; bool fsuccess; DWORD dwread, dwwritten; char chbuf [bufsize] = {0}; For (;) {fsuccess = readfile (hinputfile, chbuf, bufsize, & dwread, null); If (! Fsuccess | dwread = 0) break; fsuccess = writefile (hchildstdinwrdup, chbuf, dwread, & dwwritten, null); If (! Fsuccess) break;} If (! Closehandle (handler) handle ("Close pipe failed \ n"); closehandle (hinputfile);} void readfrompipe (lptstr handle) {handle houtputfile = createfile (handler, generic_read | generic_write, file_share_write, null, create_always, file_attribute_normal, null); If (houtputfile = success) return; bool fsuccess; DWORD dwread, dwwritten; char chbuf [bufsize] = {0}; If (! Closehandle (hchildstdoutwr) errorexit ("Closing handle failed"); For (;) {fsuccess = readfile (delimiter, chbuf, bufsize, & dwread, null); If (! Fsuccess | dwread = 0) {break;} fsuccess = writefile (houtputfile, chbuf, dwread, & dwwritten, null); If (! Fsuccess) break;} closehandle (houtputfile);} void errorexit (lptstr lpszmessage) {MessageBox (0, lpszmessage, 0, 0 );}


Ii. Named Pipe
Named pipelines have the following features:
(1) The named pipeline is bidirectional, so two processes can interact through the same pipeline.
(2) The named pipeline can be oriented not only to byte streams but also to messages. Therefore, the read process can read messages of different lengths sent by the write process.
(3) Multiple independent MPs queue instances can be named by one name. For example, several clients can use pipelines with the same name to communicate with the same server concurrently.
(4) a named pipe can be used for communication between two processes on the network, and its implementation process is exactly the same as that of the local process.
Tutorial goal: enter data A and B on the client, then send the data to the server, calculate data a + B, and then send the calculation result to the client. Multiple Clients can communicate with the same server in parallel.
Interface Design:

Difficulties:
The implementation process is relatively simple, but there is a difficulty. After the server uses the connectnamedpipe function, if a client is connected, the server can directly interact with each other. It turns out that when the pipeline is idle, the pipeline's thread functions will be infinitely blocked. If you need to stop the service now, you must end all the threads. ternimatethread can be used as a method to end the thread, but I basically don't need this function. Once this function is used, the target thread ends immediately. However, if the target thread is operating on mutex resources, kernel calls, or global variables of shared DLL, the mutex resources may not be released, and the kernel may be abnormal. Here I use overlapping I/0 to solve this problem. When creating pipe, I use the file_flag_overlapped flag. In this way, connectnamedpipe will be returned immediately, but thread blocking is implemented by the wait function waitforsingleobject, wait until the event object of the overlapped structure is set.
Main client code:

 
Code:
Void cmydlg: onsubmit () {// open the pipeline handle hpipe = createfile ("\\\\. \ PIPE \ namedpipe ", generic_read | generic_write, \ 0, null, open_existing, file_attribute_normal, null); If (hpipe = invalid_handle_value) {This-> MessageBox ("failed to open pipeline, server not started, or too many clients"); return;} DWORD nreadbyte, nwritebyte; char szbuf [1024] = {0 }; // format two integers (A, B) as the sprintf (szbuf, "% d", this-> nfirst, this-> nsecond ); // write data to the MPs queue writefile (hpipe, szbuf, strlen (szbuf), & nwritebyte, null); memset (szbuf, 0, sizeof (szbuf )); // read the server's feedback readfile (hpipe, szbuf, 1024, & nreadbyte, null); // format the returned information into an integer sscanf (szbuf, "% d ", & (this-> nresvalue); this-> updatedata (false); closehandle (hpipe );}


Main server code:

 
Code:
// Start the service void cmydlg: onstart () {cstring lppipename = "\\\\. \ PIPE \ namedpipe "; for (uint I = 0; I <nmaxconn; I ++) {// create a pipeline instance pipeinst [I]. hpipe = createnamedpipe (lppipename, pipe_access_duplex | bytes, \ pipe_type_byte | pipe_readmode_byte | pipe_wait, nmaxconn, 0, 0, 1000, null); If (pipeinst [I]. hpipe = invalid_handle_value) {DWORD dwerrorcode = getlasterror (); this-> message Box ("An error occurred while creating the MPs queue! "); Return;} // create an event object for each pipeline instance to implement overlapping Io pipeinst [I]. hevent = createevent (null, false); // assign a thread for each pipeline instance to respond to the client request pipeinst [I]. htread = afxbeginthread (serverthread, & pipeinst [I], thread_priority_normal);} This-> setwindowtext ("name MPs queue instance server (run )"); this-> MessageBox ("service started successfully");} // stop the service void cmydlg: onstop () {DWORD dwnewmode = pipe_type_byte | pipe_readmode_byte | pipe_nowai T; for (uint I = 0; I <nmaxconn; I ++) {setevent (pipeinst [I]. hevent); closehandle (pipeinst [I]. htread); closehandle (pipeinst [I]. hpipe);} This-> setwindowtext (""); this-> MessageBox (" ");} // thread service function uint serverthread (lpvoid lpparameter) {DWORD nreadbyte = 0, nwritebyte = 0, dwbyte = 0; char szbuf [max_buffer_size] = {0 }; pipe_instruct curpipeinst = * (pipe_inst Ruct *) lpparameter; overlapped overlapstruct = {0, 0, 0, 0, curpipeinst. hevent}; while (true) {memset (szbuf, 0, sizeof (szbuf); // name the connection function of the pipeline and wait for the connection from the client (only for NT) connectnamedpipe (curpipeinst. hpipe, & overlapstruct); // implements overlapping I/0 and waits for the event object waitforsingleobject (curpipeinst. hevent, infinite); // check whether I/0 has been completed. If not, it means that the event object is manually set, that is, the service needs to stop if (! Getoverlappedresult (curpipeinst. hpipe, & overlapstruct, & dwbyte, true) break; // read client request information from the pipeline if (! Readfile (curpipeinst. hpipe, szbuf, max_buffer_size, & nreadbyte, null) {MessageBox (0, "An error occurred while reading the MPs queue! ", 0, 0); break;} int A, B; sscanf (szbuf," % d ", & A, & B); pmydlg-> nfirst =; pmydlg-> nsecond = B; pmydlg-> nresvalue = a + B; memset (szbuf, 0, sizeof (szbuf); sprintf (szbuf, "% d ", pmydlg-> nresvalue); // write the feedback information to the MPs queue writefile (curpipeinst. hpipe, szbuf, strlen (szbuf), & nwritebyte, null); pmydlg-> setdlgitemint (idc_first, A, true); pmydlg-> setdlgitemint (idc_second, B, true ); pmydlg-> setdlgitemint (idc_result, pmydlg-> nresvalue, true); // disconnect the client to wait for the next customer to arrive at disconnectnamedpipe (curpipeinst. hpipe);} return 0 ;}
Related Article

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.