1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Interprocess communication through Named pipes

Discussion in 'MFC' started by shabbir, Jun 4, 2006.

  1. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,285
    Likes Received:
    364
    Trophy Points:
    83
    Threads and processes are very similar but they differ in the way they share resources. Processes are normally independent and have its own address space. Now the question comes when 2 independent processes want to communicate how do they do that. There are quite a few options for them to establish a good amount of communication protocol. Some of them are listed below.

    1. Message passing.
    2. Through Socket communication.
    3. Named piped communication.

    I will be mainly focusing on Named piped Communication.

    We start a server in a low priority thread.
    Code:
    CPipeSampleDlg *pPipeDlg = (CPipeSampleDlg*)lpData;
    
    while(TRUE) 
    { 
    	BOOL fConnected,fSuccess; 
    	CHAR chRequest[MAX_PATH]; 
    	DWORD cbBytesRead; 
    	
    	// If Pipe server is stopped break from the loop.
    	if(pPipeDlg->m_PipeHandle == NULL)
    		break;
    
    	fConnected = ConnectNamedPipe(pPipeDlg->m_PipeHandle, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED); 
    	
    	if (fConnected) 
    	{ 
    		fSuccess = ReadFile (pPipeDlg->m_PipeHandle, // handle to pipe 
    			chRequest, // buffer to receive data 
    			MAX_PATH, // size of buffer 
    			&cbBytesRead, // number of bytes read 
    			NULL); // not overlapped I/O 
    		
    		chRequest[cbBytesRead] = '\0';
    		CString msg;
    		msg.Format("Received string : %s\r\n",chRequest);
    		pPipeDlg->ShowLastError(msg);
    
    		FlushFileBuffers(pPipeDlg->m_PipeHandle); 
    		DisconnectNamedPipe(pPipeDlg->m_PipeHandle); 
    	}
    } 
    return 0;
    
    The thread waits for a client to connect to it as passes some data to the server.

    Code:
    CString szPipeName;
    szPipeName = _T("\\\\.\\pipe\\PipeTest");
    
    BOOL bret = FALSE;
    
    //first we will try to connect to the exising PIPE
    bret = ::WaitNamedPipe((LPCSTR)szPipeName,PROVIDER_WAIT_TIME);
    //the named 
    if(bret == FALSE)
    {
    	ShowLastError();
    	return;
    }
    else
    {
    	//the PIPE is available so we will do the rest of the work in a thread
    	ShowLastError("PIPE is available for connection");
    	BOOL flg;
    	DWORD dwWrite;
    
    	CString szPipeUpdate;
    	
    	HANDLE hPipeHandle = ::CreateFile((LPCSTR)szPipeName,GENERIC_WRITE,0,NULL,
    		OPEN_EXISTING,0,NULL);
    	
    	szPipeUpdate = _T("WM_USER_MESSAGE");
    	
    	flg = WriteFile(hPipeHandle, szPipeUpdate, strlen(szPipeUpdate), &dwWrite, NULL);
    
    	if (FALSE == flg)
    		ShowLastError("Sending string : " + szPipeUpdate + " Failed");
    	else
    		ShowLastError("Sending string : " + szPipeUpdate);
    
    	CloseHandle(hPipeHandle);
    }
    The client connects to the pipe creates a file to be wriiten. Writes the file and returns. It does not wait for the server to complete the process with the data. This is asynchronous mode of tranfer.

    I have used the name of the pipe as "\\\\.\\pipe\\PipeTest" which connects to the server on the local machine but it can be used to specify some other name of the server or even the ip address where the server is running like "\\\\127.0.0.1\\pipe\\PipeTest"

    I have similar code in VB with same API's for you to see.
    Server code
    Code:
    Dim ovl As OVERLAPPED
    Dim fConnected, fSuccess As Boolean
    Dim iConnectionStatus As Long
    Dim chRequest As String
    Dim cbBytesRead As Long
    
    Do
    	DoEvents
    	
    	If PipeHandle = 0 Then
    		Exit Do
    	End If
    	
    	iConnectionStatus = ConnectNamedPipe(PipeHandle, ovl)
    	
    	If iConnectionStatus <> 0 Then
    		fConnected = True
    	Else
    		If Err.LastDllError = ERROR_PIPE_CONNECTED Then
    			fConnected = True
    		Else
    			fConnected = False
    		End If
    	End If
    	
    	If fConnected = True Then
    		chRequest = Space(MAX_PATH)
    		fSuccess = ReadFile(PipeHandle, chRequest, MAX_PATH, cbBytesRead, ovl)
    	 
    		If Not fSuccess Or cbBytesRead = 0 Then
    		   Exit Do
    		End If
    	
    		ShowLastStatus "Recieved : " + chRequest
    		FlushFileBuffers ByVal PipeHandle
    		DisconnectNamedPipe ByVal PipeHandle
    	End If
    Loop
    Client code
    Code:
    Dim bret As Boolean
    bret = False
       
    bret = WaitNamedPipe(szPipeName, PROVIDER_WAIT_TIME)
    If bret = False Then
    	ShowLastStatus
    Else
    	ShowLastStatus "PIPE is available for connection"
    	Dim flg As Boolean
    	Dim dwWrite As Long
    	Dim szPipeUpdate As String
    	Dim hPipeHandle As Long
    	Dim sa As SECURITY_ATTRIBUTES
    	Dim ovl As OVERLAPPED
    			
    	hPipeHandle = CreateFile(szPipeName, GENERIC_WRITE, 0, sa, OPEN_EXISTING, 0, 0)
    	
    	szPipeUpdate = "HI FROM CLIENT"
    	
    	flg = WriteFile(hPipeHandle, szPipeUpdate, Len(szPipeUpdate), dwWrite, ovl)
    
    	If False = flg Then
    		ShowLastStatus "Sending string : " + szPipeUpdate + " Failed"
    	Else
    		ShowLastStatus "Sending string : " + szPipeUpdate
    	End If
    End If
    
    API's
    Code:
    'Constants
    Public Const PROVIDER_WAIT_TIME = 30
    Public Const PIPE_ACCESS_DUPLEX = &H3
    Public Const FILE_FLAG_OVERLAPPED = &H40000000
    Public Const PIPE_TYPE_MESSAGE = &H4
    Public Const PIPE_WAIT = &H0
    Public Const MAX_PATH = 260
    Public Const INVALID_HANDLE_VALUE = -1
    Public Const FORMAT_MESSAGE_ALLOCATE_BUFFER = &H100
    Public Const FORMAT_MESSAGE_FROM_SYSTEM = &H1000
    Public Const FORMAT_MESSAGE_IGNORE_INSERTS = &H200
    Public Const LANG_NEUTRAL = &H0
    Public Const GENERIC_WRITE = &H40000000
    Public Const OPEN_EXISTING = 3
    Public Const ERROR_PIPE_CONNECTED = 535&
    
    'Types
    Public Type SECURITY_ATTRIBUTES
            nLength As Long
            lpSecurityDescriptor As Long
            bInheritHandle As Long
    End Type
    Public Type OVERLAPPED
            Internal As Long
            InternalHigh As Long
            offset As Long
            OffsetHigh As Long
            hEvent As Long
    End Type
    
    'Functions
    Public Declare Function CreateNamedPipe Lib "kernel32" Alias "CreateNamedPipeA" (ByVal lpName As String, ByVal dwOpenMode As Long, ByVal dwPipeMode As Long, ByVal nMaxInstances As Long, ByVal nOutBufferSize As Long, ByVal nInBufferSize As Long, ByVal nDefaultTimeOut As Long, lpSecurityAttributes As SECURITY_ATTRIBUTES) As Long
    Public Declare Function FormatMessage Lib "kernel32" Alias "FormatMessageA" (ByVal dwFlags As Long, lpSource As Any, ByVal dwMessageId As Long, ByVal dwLanguageId As Long, ByVal lpBuffer As String, ByVal nSize As Long, Arguments As Long) As Long
    Public Declare Function ConnectNamedPipe Lib "kernel32" (ByVal hNamedPipe As Long, lpOverlapped As OVERLAPPED) As Long
    Public Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, lpOverlapped As OVERLAPPED) As Long
    Public Declare Function FlushFileBuffers Lib "kernel32" (ByVal hFile As Long) As Long
    Public Declare Function DisconnectNamedPipe Lib "kernel32" (ByVal hNamedPipe As Long) As Long
    Public Declare Function WaitNamedPipe Lib "kernel32" Alias "WaitNamedPipeA" (ByVal lpNamedPipeName As String, ByVal nTimeOut As Long) As Long
    Public Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As SECURITY_ATTRIBUTES, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
    Public Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, lpOverlapped As OVERLAPPED) As Long
    Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
    
    I am not a VB expert and if I you have any suggestion feel free to post a comment.

    No need to copy and paste the code as I have attached the VB and VC Source codes for you to download.
     

    Attached Files:

  2. lplover2k

    lplover2k New Member

    Joined:
    Feb 4, 2007
    Messages:
    15
    Likes Received:
    0
    Trophy Points:
    0
    hi, can u give an example to send a .jpg file plz?
     
  3. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,285
    Likes Received:
    364
    Trophy Points:
    83
    The data can be anything and not necessarily be string.
     
  4. lplover2k

    lplover2k New Member

    Joined:
    Feb 4, 2007
    Messages:
    15
    Likes Received:
    0
    Trophy Points:
    0
    should i serialize the file before sending it?

    i replace "szPipeUpdate = _T("WM_USER_MESSAGE");" by what plz?
     
  5. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,285
    Likes Received:
    364
    Trophy Points:
    83
    Read the file in the binary mode into a buffer and send the buffer.
     
  6. lplover2k

    lplover2k New Member

    Joined:
    Feb 4, 2007
    Messages:
    15
    Likes Received:
    0
    Trophy Points:
    0
    how do i do that??
     
  7. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,285
    Likes Received:
    364
    Trophy Points:
    83
    Refer to the following articles for that.

    [thread=2977]File read write in plain C[/thread].
    [thread=1323]File Handling in C - File Pointers[/thread].
    [thread=1268]File Splitter and Merger[/thread].
     
  8. lplover2k

    lplover2k New Member

    Joined:
    Feb 4, 2007
    Messages:
    15
    Likes Received:
    0
    Trophy Points:
    0
    hmm..thx but can u can u write an example how to send a file with your code to ease things up?
     
  9. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,285
    Likes Received:
    364
    Trophy Points:
    83
    If I have the time I can try but you can assume it may take ages as well.
     
  10. lplover2k

    lplover2k New Member

    Joined:
    Feb 4, 2007
    Messages:
    15
    Likes Received:
    0
    Trophy Points:
    0
    oh ok...so it's that complicated?.. :(
     
  11. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,285
    Likes Received:
    364
    Trophy Points:
    83
    [comment]You can always assume that[/comment]
     
  12. lplover2k

    lplover2k New Member

    Joined:
    Feb 4, 2007
    Messages:
    15
    Likes Received:
    0
    Trophy Points:
    0
    i think i going to read each pixel of the jpg image and send them in series in a string and i reassemble them at destination...
     
  13. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,285
    Likes Received:
    364
    Trophy Points:
    83
    That will corrupt the final output file and send them as bytes.
     
  14. parvez.yu

    parvez.yu New Member

    Joined:
    Feb 14, 2008
    Messages:
    100
    Likes Received:
    0
    Trophy Points:
    0
    ipc is quite complicated ,can you give me some link from where i can gain some knowledge
     
  15. jithoos

    jithoos New Member

    Joined:
    May 22, 2008
    Messages:
    1
    Likes Received:
    0
    Trophy Points:
    0
    I have a console exe, which simple does like this.

    _tprintf(_T("Hello..."));
    Sleep(2000);
    _tprintf(_T("Good Morning.."));
    Sleep(3000);
    _tprintf(_T("How r u??"));

    I want invoke this exe from my Dialog appication, and display these outputs in a ListBox. I did it using CreatePipe(), CreateProcess() and ReadFile() functions. But the problem now is when execution reaches the ReadFile() function, it stucks for some time(upto the completion of child process) . And instead of getting "Hello", RedFile() reads entire output texts ("Hello.. GoodMorning..How r u??") as a whole. But what i want is to instantly read the output of child exe whenver it prints a new text.. Wht to do??
     

Share This Page