ali-ent / apploader

portable app server written by c#. easy to write a program running with console or windows service.
4 stars 3 forks source link

passing socket to child process and more about multi-remoting? #4

Open wsky opened 11 years ago

wsky commented 11 years ago

http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/94ba760c-7080-4614-8a56-15582c48f900/

passing socket handle http://stackoverflow.com/questions/4604273/pass-socket-handle-from-net-to-unmanaged-child-process

http://stackoverflow.com/questions/603365/socket-passing-between-processes?rq=1

Shared Sockets http://msdn.microsoft.com/en-us/library/ms740478.aspx

Socket Duplication - Part 1 Passing a socket to a new AppDomain

So to make it easy, in managed code, once a socket has been duplicated by a process, it is automatically closed at the source process end. Since duplication increases the reference count on the handle of the socket, the socket is valid even when one of the descriptors is closed. Hence the API name DuplicateAndClose.

namespace socketDuplication
{
    public class DuplicationSample
    {
        public static void Main()
        {
            //create a socket
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            //listen on an  ipaddress and port
            sock.Bind(new IPEndPoint(ipAddress, port));
            sock.Listen(5);
            //Duplicate the socket
SocketInformation socketInfo = sock.DuplicateAndClose(Process.GetCurrentProcess().Id);

            //create a new appdomain
AppDomain TestDomain = AppDomain.CreateDomain("DuplicateSocketsTest");
DuplicationNewAppDomain newAppDomain = (DuplicationNewAppDomain)TestDomain.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, "SocketDuplication. DuplicationNewAppDomain");

            //transfer socketinfo to the new appdomain
            newAppDomain.TransferSocket(socketInfo);
        }
    }

    public class DuplicationNewAppDomain : MarshalByRefObject
    {
        void TransferSocket(SocketInformation sockInfo)
        {
        }
    }
 }

http://blogs.msdn.com/b/malarch/archive/2005/12/14/503884.aspx

wsky commented 11 years ago

Custom channel of .net remoting that share tcp socket?

http://65.39.148.52/Articles/4054/Extensible-NET-remoting-framework

http://65.39.148.52/Articles/1659/Using-MSMQ-for-Custom-Remoting-Channel

UDP Custom Channel Example http://www.winsocketdotnetworkprogramming.com/clientservernetremotingnetwork12f.html

http://www.rikware.com/post/Asynchronous-Remoting-Server.aspx

Advanced .Net Remoting http://books.google.com.hk/books?id=rbW3qBrWiAcC&printsec=frontcover&hl=zh-CN#v=onepage&q&f=false

http://www.codeproject.com/Articles/4175/NET-Remoting-Customization-Made-Easy-Custom-Sinks

sinks

[MS-NRTP]: .NET Remoting: Core Protocol Relationships between .NET Remoting protocols http://msdn.microsoft.com/en-us/library/cc237297(v=prot.20).aspx Protocol Examples http://msdn.microsoft.com/en-us/library/cc237454(v=prot.20).aspx

BinaryFormatter is too slower http://www.codeproject.com/Articles/311944/BinaryFormatter-or-Manual-serializing

ServiceRequest/Respone Stream Usage:

TcpClientChannel ClientRequestStream

https://github.com/wsky/System.Runtime.Remoting/blob/master/ManagedLibraries/Remoting/Channels/TCP/TcpClientSocketManager.cs/1305376/TcpClientSocketManager.cs#L112

// output preamble and version
            WritePreambleAndVersion(headerStream); 
            // output opcode 
            if (!_bOneWayRequest)
                WriteUInt16(TcpOperations.Request, headerStream); 
            else
                WriteUInt16(TcpOperations.OneWayRequest, headerStream);
            // output content delimiter style
            WriteUInt16(TcpContentDelimiter.ContentLength, headerStream); 
            WriteInt32(contentLength, headerStream);

            // output request uri 
            WriteUInt16(TcpHeaders.RequestUri, headerStream);
            WriteByte(TcpHeaderFormat.CountedString, headerStream); 
            WriteCountedString(uri, headerStream);

            // output rest of headers
            WriteHeaders(headers, headerStream); 

TcpServerChannel GetRequestStream

https://github.com/wsky/System.Runtime.Remoting/blob/master/ManagedLibraries/Remoting/Channels/TCP/TcpServerChannel.cs/1305376/TcpServerChannel.cs#L542

internal void ServiceRequest(Object state)
        {
            TcpServerSocketHandler streamManager = (TcpServerSocketHandler)state;

            ITransportHeaders headers = streamManager.ReadHeaders();
            Stream requestStream = streamManager.GetRequestStream(); 
            headers["__CustomErrorsEnabled"] = streamManager.CustomErrorsEnabled(); 

            // process request 
            ServerChannelSinkStack sinkStack = new ServerChannelSinkStack();
            sinkStack.Push(this, streamManager);

            IMessage responseMessage; 
            ITransportHeaders responseHeaders;
            Stream responseStream; 

https://github.com/wsky/System.Runtime.Remoting/blob/master/ManagedLibraries/Remoting/Channels/TCP/TcpStreams.cs/1305376/TcpStreams.cs#L289

// content length must come next (may be chunked or a specific length) 
            ReadContentLength(out _bChunked, out _contentLength);
//https://github.com/wsky/System.Runtime.Remoting/blob/master/ManagedLibraries/Remoting/Channels/TCP/TcpSocketManager.cs/1305376/TcpSocketManager.cs#L90

            // read to end of headers
            ReadToEndOfHeaders(headers);
//https://github.com/wsky/System.Runtime.Remoting/blob/master/ManagedLibraries/Remoting/Channels/TCP/TcpSocketManager.cs/1305376/TcpSocketManager.cs#L116
wsky commented 11 years ago

Simple but quite efficient BinaryFormatter replacement for .NET Remoting. https://github.com/vadimskipin/Protobuf.Remoting

https://github.com/vadimskipin/Protobuf.Remoting/blob/master/Protobuf.Remoting/ProtobufMessageReader.cs

while (Serializer.NonGeneric.TryDeserializeWithLengthPrefix(stream, PrefixStyle.Base128, GetTaggedValueType, out value))
            {
                switch (_lastTag)
                {
                    case ProtobufMessageTags.CallContext:
                        CallContext = (LogicalCallContext)BinaryFormatterHelper.DeserializeObject((byte[])value);
                        break;

                    case ProtobufMessageTags.Headers:
                        Headers = (Header[])BinaryFormatterHelper.DeserializeObject((byte[])value);
                        break;

                    case ProtobufMessageTags.Exception:
                        Exception = (Exception)BinaryFormatterHelper.DeserializeObject((byte[])value);
                        break;

                    case ProtobufMessageTags.Result:
                        Result = GetValue(_returnType, value);
                        break;

                    default:
                        {
                            int index = _lastTag - ProtobufMessageTags.FirstParameter;
                            Args[index] = GetValue(_parameters[index].ParameterType, value);
                        }
                        break;
                }
            }

FormatterSink will prepare Message(Message.Header).

TransportSink will send TransportHeader.

ChunkedMemoryStream headerStream = new ChunkedMemoryStream(CoreChannel.BufferPool);

            // output preamble and version
            WritePreambleAndVersion(headerStream); 
            // output opcode 
            if (!_bOneWayRequest)
                WriteUInt16(TcpOperations.Request, headerStream); 
            else
                WriteUInt16(TcpOperations.OneWayRequest, headerStream);
            // output content delimiter style
            WriteUInt16(TcpContentDelimiter.ContentLength, headerStream); 
            WriteInt32(contentLength, headerStream);

            // output request uri 
            WriteUInt16(TcpHeaders.RequestUri, headerStream);
            WriteByte(TcpHeaderFormat.CountedString, headerStream); 
            WriteCountedString(uri, headerStream);

            // output rest of headers
            WriteHeaders(headers, headerStream); 

            headerStream.WriteTo(NetStream); 
            headerStream.Close(); 
wsky commented 11 years ago

servicestack replace formatter? https://groups.google.com/forum/#!msg/servicestack/Jl1xjlLH-4E/iImqyT8NlP0J

wsky commented 11 years ago

Mono's impl of Remoting look simply.

https://github.com/mono/mono/blob/master/mcs/class/System.Runtime.Remoting/System.Runtime.Remoting.Channels.Tcp/TcpMessageIO.cs

wsky commented 11 years ago

TcpContentDelimiter.Chunked

protected void ReadContentLength(out bool chunked, out int contentLength)
        { 
            contentLength = -1;

            UInt16 header = ReadUInt16();
            if (header == TcpContentDelimiter.Chunked) 
            {
                chunked = true; 
            } 
            else
            if (header == TcpContentDelimiter.ContentLength) 
            {
                chunked = false;
                contentLength = ReadInt32();
            } 
            else
            { 
                throw new RemotingException( 
                    String.Format(
                        CultureInfo.CurrentCulture, CoreChannel.GetResourceString("Remoting_Tcp_ExpectingContentLengthHeader"), 
                        header.ToString(CultureInfo.CurrentCulture)));

            }
        } // ReadContentLength 

HttpSocketHandler.cs

if (String.Compare(headerName, "Transfer-Encoding", StringComparison.OrdinalIgnoreCase) == 0)
                {
                    if (String.Compare(headerValue, "chunked", StringComparison.OrdinalIgnoreCase) == 0) 
                    {
                        bChunked = true; 
                    } 
                }

http://www.wrsaw.cn/Article/ShowArticle.asp?ArticleID=13833

maybe it useless.

wsky commented 11 years ago

I write a parser for remoting core-protocol helping understand how it works.

https://github.com/wsky/RemotingProtocolParser