Thread: Named Pipe Problems.

  1. #1
    Codebot
    Join Date
    Jun 2004
    Location
    Toronto
    Posts
    195

    Named Pipe Problems.

    Earlier i inquired what methods were available for sending data between apps. I decided to use a named pipe, and now it works like a charm.

    Until I found a weird bug.

    The bug is that the application thats recieving data from the pipe, stops recieving it after a while. Im starting to think that the reason for this is that the pipe has something sitting in it, while i send more data up there. Is it possible for a pipe to stop working if i send data in there without recieving the data that was in there previously?? Is there an alternate explanation why my pipe stops working?

    Writing to the pipe gives me no error while i dont get anything at the other end.
    Founder and avid member of the Internationsl Typo Associateion

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    You're not getting answers without posting code.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Codebot
    Join Date
    Jun 2004
    Location
    Toronto
    Posts
    195
    The code is rather large. Dont say i didnt warn you.

    This is the Struct I am sending through. DATASIZE = 1024.

    Code:
    struct Instruction
    {
    	int StructID;
    	int Size;
    	char Data[DATASIZE];				// User defined Data (ie. Custom structs etc.)
    };

    My pipe structure, contains all the necessary things for getting a pipe started.
    Code:
    typedef struct 
    { 
       OVERLAPPED Overlap; 
       HANDLE PipeInst; 
       DWORD Read;
       DWORD ToWrite; 
       DWORD State; 
       BOOL PendingIO;
       DWORD Id;
    } PIPEINST;
    This code creates a pipe on the CLIENT side.

    Code:
    bool Pipe::Create()
    {
    	char PipeName[35];
    	PipeInst.Id = (DWORD) App;
    
    	memset(PipeName, 0, 35);
    	sprintf(PipeName, "\\\\.\\pipe\\%X", PipeInst.Id);
    
    	// Create an event to use with overlapping
    	Events = CreateEvent(
    							NULL,    // default security attribute 
    							TRUE,    // manual-reset event 
    							TRUE,    // initial state = signaled 
    							NULL);   // unnamed event object 
    
    	if (Events)
    	{
    		// Set the new overlap event
    		PipeInst.Overlap.hEvent = Events;
    
    		PipeInst.PipeInst = CreateNamedPipe( 
    							PipeName,	             // pipe name 
    							PIPE_ACCESS_DUPLEX |     // read/write access 
    							FILE_FLAG_OVERLAPPED,    // overlapped mode (asych mode)
    							PIPE_TYPE_BYTE |
    							PIPE_READMODE_BYTE |
    							PIPE_WAIT,               // blocking mode 
    							1,		                 // number of instances 
    							BUFSIZE,			     // output buffer size 
    							BUFSIZE,				 // input buffer size 
    							PIPE_TIMEOUT,            // client time-out 
    							NULL);                   // default security attributes 
    
    		// Attempt to connect to the newly created pipe
    		PipeInst.PendingIO = ConnectToNewClient( 
    							PipeInst.PipeInst, 
    							&PipeInst.Overlap); 
    
    		if (PipeInst.PendingIO)
    		{
    			SendMessage(Service, STRIKE_REGISTER_APPLICATION, (WPARAM) PipeInst.Id, NULL);
    		}
    	}
    
    	return PipeInst.PendingIO ? true : false;
    }

    This code Connects to the pipe from the SERVER side:
    Code:
    bool Pipe::Connect(char *PipeName)
    {
    	bool Rtrn = false;
    
    	if (PipeName)
    	{
    		// Attempt to connect to a pipe
    		PipeInst.PipeInst = CreateFile( 
    								PipeName,		// pipe name 
    								GENERIC_READ |  // read and write access 
    								GENERIC_WRITE, 
    								0,              // no sharing 
    								NULL,           // default security attributes
    								OPEN_EXISTING,  // opens existing pipe 
    								0,              // default attributes 
    								NULL);          // no template file 
    
    		// If we have a good handle then exit correctly
    		if (PipeInst.PipeInst != INVALID_HANDLE_VALUE) 
    		{
    			Rtrn = true;
    		}
    	}
    
    	return Rtrn && PipeInst.PipeInst ? true : false;
    }
    Here the CLIENT reads from the pipe whenever there is a new piece of data available (i do this by notifying the client by using SendMessage() with a custom windows message).

    Code:
    void *Pipe::GetData(int *StructID)
    {
    	void *Rtrn = NULL;
    	Instruction RecieveData;
    	unsigned int Written = 0;
    
    	if (PipeInst.PipeInst)
    	{
    		memset(&RecieveData, 0, sizeof(Instruction));
    
    		// Get the size of the Buffer
    		ReadFile( 
    								PipeInst.PipeInst,	// pipe handle 
    								&RecieveData,		// buffer to receive reply 
    								sizeof(Instruction),// size of buffer 
    								(LPDWORD) &Written,			// number of bytes read 
    								NULL);			    // not overlapped 
    
    		Rtrn = (void *) new unsigned char[RecieveData.Size];
    
    		if (Rtrn)
    		{
    			memcpy(Rtrn, &RecieveData.Data, (size_t) RecieveData.Size);
    			*StructID = RecieveData.StructID;
    		}
    	}
    
    	return Rtrn;
    }
    This is on the server side, where the server send data down the pipe and then sends a message to the client saying there is date to be read.
    Code:
    bool Pipe::WriteData(void *Data, int Size, int StructID)
    {
    	bool Rtrn = false;
    	unsigned int Written = 0;
    	Instruction DataSend;
    
    	if (PipeInst.PipeInst && Data && Size)
    	{
    		memset(&DataSend, 0, sizeof(Instruction));
    
    		DataSend.Size = Size;
    		DataSend.StructID = StructID;
    		memcpy(&DataSend.Data, Data, Size);
    
    		WriteFile( 
    							PipeInst.PipeInst,      // pipe handle 
    							&DataSend,		             // message 
    							sizeof(Instruction),			// message length 
    							(LPDWORD) &Written,             // bytes written 
    							NULL);                  // not overlapped 
    
    		if (Written == sizeof(Instruction))
    		{
    			SendMessage(App, STRIKE_RECIEVED_INSTRUCTION, NULL, NULL);
    			Rtrn = true;
    		}
    	}
    
    	return Rtrn;
    }
    OK that was long. Basically it works this way. The CLIENT creates a pipe, then sends a message to the SERVER saying "hey, theres a pipe created, talk to me". The server connects to the pipe and starts writing data. When data is written, it sends a message to the CLIENT saying "hey, thers data to be read". The client then reads the data.

    I believe that the problem might be that the pipe gets two structs sent down the pipe before the client is able to pick it up. the client app is firefox, so therefore it may not have the time to read form the message pump as frequently.

    Thats my interpretation of this. Am i right or can someone offer some other solution?
    Founder and avid member of the Internationsl Typo Associateion

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. No clue how to make a code to solve problems!
    By ctnzn in forum C Programming
    Replies: 8
    Last Post: 10-16-2008, 02:59 AM
  2. still problems with ceasar shift
    By trevordunstan in forum C Programming
    Replies: 2
    Last Post: 09-14-2008, 01:49 AM
  3. Having trouble with a named pipe
    By crazeinc in forum C Programming
    Replies: 2
    Last Post: 05-13-2005, 01:00 AM
  4. Reading data from consecutively named files
    By a1pro in forum C Programming
    Replies: 10
    Last Post: 04-15-2005, 01:48 AM
  5. Named Pipes with .NET?
    By michl in forum C# Programming
    Replies: 2
    Last Post: 04-28-2003, 12:54 AM