locked
Custom FastCGI client - TCP Protocol RRS feed

  • Question

  • User-2087712110 posted

    Hi,

     I see that you can specify the FastCGI application to use the TCP communication protocol (instead of named pipes) but how do you set this comms up? I am thinking that the FCGI application must be "listening" on a certain port. How do you inform the FastCGI server which port to send this comms to?

     
    Regards,

    Pieter Breed
     

    Tuesday, November 6, 2007 2:41 AM

Answers

  • User-679828332 posted

    Hi Pieter,

    It will be exciting to see a c# FastCGI implementation! Random thoughts:

    - checkout the Java one at www.fastcgi.com (i haven't looked, but imagine it would be similar)

    - try this out http://blogs.iis.net/rickjames/archive/2007/02/04/fake-fastcgi-web-server.aspx

    - If you're only targeting Windows, then I'd try get the named pipes implementation working ahead of TCP (It is probably faster, allows you to impersonate if you choose to, it is the default protocol, I found it simpler to implement than TCP)

    The standard input handle for the FastCGI process is actually a handle to a named pipe or a socket. You need to co-erce this into a type c# will understand. I'm not an expert c# programmer, so the rest of this information may be wrong:

    - I could not find a way to produce a System.Net.Sockets.Socket using a pre-existing socket. (if there were a way to create your own SocketInformation struct, with the correct values, then you'd be good to go..)

    - I could not find a built-in method for accessing named pipes. (though it appears this will be available in the next .net fx release: http://blogs.msdn.com/bclteam/archive/2006/12/07/introducing-pipes-justin-van-patten.aspx)

    Cheerz,

    Rick.

    • Marked as answer by Anonymous Tuesday, September 28, 2021 12:00 AM
    Tuesday, November 6, 2007 12:54 PM
  • User-2087712110 posted

    Hi Rick,

    I found the following on MSDN: Is this what you are talking about? (http://msdn.microsoft.com/en-us/library/ms682075.aspx)

    However, the SetStdHandle function can redirect the standard handles by changing the handle associated with STDIN, STDOUT, or STDERR. Because the parent's standard handles are inherited by any child process, subsequent calls to GetStdHandle return the redirected handle. A handle returned by GetStdHandle may, therefore, refer to something other than console I/O. For example, before creating a child process, a parent process can use SetStdHandle to set a pipe handle to be the STDIN handle that is inherited by the child process

    If this is correct, can I use this HANDLE I received from GetStdHandle() to look up the named pipe?

    Again, this is what I found on MSDN: (http://msdn.microsoft.com/en-us/library/aa365592.aspx)

    A named pipe client uses the CreateFile function to open a handle to a named pipe...

    The handle returned by CreateFile defaults to byte-read mode, blocking-wait mode, overlapped mode disabled, and write-through mode disabled...

    The client can use the SetNamedPipeHandleState function to enable nonblocking mode by specifying PIPE_NOWAIT or to enable message-read mode by specifying PIPE_READMODE_MESSAGE...

    So, the way I understand this is that I would not need to call CreateFile() (the FastCGI server would have done that, right?) The HANDLE I would have received from GetStdHandle() would in effect be the handle you would get if you called CreateFile()?

    I might possibly have to call SetNamedPipeHandleStates()?

    I would then be able to ReadFile() and WriteFile() using this handle?

    I am sorry that I am pestering you with so much questions, but my own C++ career stopped before it got to this level. 

    Regards,

    Pieter 

     

     

    • Marked as answer by Anonymous Tuesday, September 28, 2021 12:00 AM
    Wednesday, November 7, 2007 8:29 AM
  • User-679828332 posted

    Hi Pieter, 

    That's it. I don't think you'd need to call SetNamedPipeHandleStates. ReadFile should work on the handle provided by GetStdHandle( STD_INPUT_HANDLE ).

    Here's an example of someone playing with named pipes from .net fx 2:

    http://blog.paranoidferret.com/index.php/2007/07/25/interprocess-communication-using-named-pipes-in-csharp

    Cheerz,

    Rick.

    • Marked as answer by Anonymous Tuesday, September 28, 2021 12:00 AM
    Wednesday, November 7, 2007 12:58 PM

All replies

  • User-679828332 posted

    Hi Pieter,

    Congrats on the world cup! :-)

    FastCGI protocol (www.fastcgi.com) requires that the STDIN handle is replaced with the transport handle. In the case of TCP, we create and bind a socket to an ephemeral port before handing to the FastCGI process. We've tested this with libfcgi, so if you're using that it should just work.. Note that for both named pipes and TCP we expect the FastCGI process to honour the FCGI_KEEP_CONN flag.

    Cheerz,

    Rick.

    Tuesday, November 6, 2007 10:35 AM
  • User-2087712110 posted

    Hi Rick,

    re Rugby: Yeah, since we won that damned thing, South Africa has been pretty crazy. Most of its been good though ;)

    I am not actually using libfcgi, but rather implementing a library on the same level, ie, doing the low-level stuff, parsing the stream, reading the records and that kind of thing. Hence my questions around these issues. I am at the point where, if I create a MemoryStream by hand, I can read the FCGI records out more or less correctly. I would now like to get some real input data from a FCGI server, to further the work.

    I am sorry but my knowledge fails me wrt "create and bind a socket to an ephemeral port before handing to the FastCGI process" as you said. Where can I find more info about this technique? (I am using C# 2.0) My first step would be to create a listener that just records the input bytes as sent from the server, and then fail. I could then use these bytes in my testing before trying to drink from the firehose.

    Regards,

    Pieter

    Tuesday, November 6, 2007 12:18 PM
  • User-679828332 posted

    Hi Pieter,

    It will be exciting to see a c# FastCGI implementation! Random thoughts:

    - checkout the Java one at www.fastcgi.com (i haven't looked, but imagine it would be similar)

    - try this out http://blogs.iis.net/rickjames/archive/2007/02/04/fake-fastcgi-web-server.aspx

    - If you're only targeting Windows, then I'd try get the named pipes implementation working ahead of TCP (It is probably faster, allows you to impersonate if you choose to, it is the default protocol, I found it simpler to implement than TCP)

    The standard input handle for the FastCGI process is actually a handle to a named pipe or a socket. You need to co-erce this into a type c# will understand. I'm not an expert c# programmer, so the rest of this information may be wrong:

    - I could not find a way to produce a System.Net.Sockets.Socket using a pre-existing socket. (if there were a way to create your own SocketInformation struct, with the correct values, then you'd be good to go..)

    - I could not find a built-in method for accessing named pipes. (though it appears this will be available in the next .net fx release: http://blogs.msdn.com/bclteam/archive/2006/12/07/introducing-pipes-justin-van-patten.aspx)

    Cheerz,

    Rick.

    • Marked as answer by Anonymous Tuesday, September 28, 2021 12:00 AM
    Tuesday, November 6, 2007 12:54 PM
  • User-2087712110 posted

    Hi Rick,

    I found the following on MSDN: Is this what you are talking about? (http://msdn.microsoft.com/en-us/library/ms682075.aspx)

    However, the SetStdHandle function can redirect the standard handles by changing the handle associated with STDIN, STDOUT, or STDERR. Because the parent's standard handles are inherited by any child process, subsequent calls to GetStdHandle return the redirected handle. A handle returned by GetStdHandle may, therefore, refer to something other than console I/O. For example, before creating a child process, a parent process can use SetStdHandle to set a pipe handle to be the STDIN handle that is inherited by the child process

    If this is correct, can I use this HANDLE I received from GetStdHandle() to look up the named pipe?

    Again, this is what I found on MSDN: (http://msdn.microsoft.com/en-us/library/aa365592.aspx)

    A named pipe client uses the CreateFile function to open a handle to a named pipe...

    The handle returned by CreateFile defaults to byte-read mode, blocking-wait mode, overlapped mode disabled, and write-through mode disabled...

    The client can use the SetNamedPipeHandleState function to enable nonblocking mode by specifying PIPE_NOWAIT or to enable message-read mode by specifying PIPE_READMODE_MESSAGE...

    So, the way I understand this is that I would not need to call CreateFile() (the FastCGI server would have done that, right?) The HANDLE I would have received from GetStdHandle() would in effect be the handle you would get if you called CreateFile()?

    I might possibly have to call SetNamedPipeHandleStates()?

    I would then be able to ReadFile() and WriteFile() using this handle?

    I am sorry that I am pestering you with so much questions, but my own C++ career stopped before it got to this level. 

    Regards,

    Pieter 

     

     

    • Marked as answer by Anonymous Tuesday, September 28, 2021 12:00 AM
    Wednesday, November 7, 2007 8:29 AM
  • User-679828332 posted

    Hi Pieter, 

    That's it. I don't think you'd need to call SetNamedPipeHandleStates. ReadFile should work on the handle provided by GetStdHandle( STD_INPUT_HANDLE ).

    Here's an example of someone playing with named pipes from .net fx 2:

    http://blog.paranoidferret.com/index.php/2007/07/25/interprocess-communication-using-named-pipes-in-csharp

    Cheerz,

    Rick.

    • Marked as answer by Anonymous Tuesday, September 28, 2021 12:00 AM
    Wednesday, November 7, 2007 12:58 PM
  • User-2087712110 posted

    Hi Rick,

    Thanks, your comments are really helpful and I have progressed far since yesterday. I am using the fakecgi.exe helper-app and I ran into another problem:

    I used the same method as the guy in that link that you sent in your previous post, ie, wrapping the SafeFileHandle up in a FileStream. I find that it blocks on reading from that handle and I suspect its because I've read everything out of it. So the normal Read() operation is not returning with a "0 bytes read" indicator, like I expected.

    My assumptions were that this would in fact be the behavior, but since its not, I need to dream up an alternative strategy.

    • I saw here that you can modify the named pipe handle to return immediately if there aren't any data in the pipe (nonblocking-wait handle), but that same MSDN page contains an ominous-sounding warning that this mode is for use with Microsoft® LAN Manager version 2.0. I am not trying to do overlapped I/O, but neither am I MS LAN manager 2. So may I use this mode or not? If I do modify the handle to be in a non-blocking read mode, will that affect the server (IE will that be bad?)
    • Or should I read only as many bytes from the stream as I really need, and modify my strategy not to try and "empty out" the whole stream in one go?

    Regards,

    Pieter 

     

    Thursday, November 8, 2007 3:01 AM
  • User-679828332 posted

    I would read a header, parse it, read any associated body, use it (or buffer it) and then start reading again..

    Thursday, November 8, 2007 7:36 PM