Вы находитесь на странице: 1из 211

. . .

Microsoft .NET Framework

. ., . .

, 2006

....................................................................................................................................2
1.

.................................................................4

1.1.

____________________________________ 4

1.2.

. ________ 9

1.3.

______________________________ 10

1.4.

_____________________________________ 14

2.

...................................18

2.1.

____________ 18

2.2.

______________________________________________ 19

2.3.

___________________________________________ 21

2.4.

_________________________________ 23

......................................................................................26
..............................................................................27
......................................................................................28
......................................................28
..............................................................29
2.5.

___________________________________________ 32

2.6.

________________________________________ 33

2.7.

_____________________________ 35

2.8.

Microsoft .NET Framework ____________________ 36

3.

..........................................38

3.1.

_______________________ 38

3.2.

XML XML___________________________________________ 41

3.3.

SOAP: ______________________ 44

3.4.

WSDL: ________________ 45

3.5.

________________________ 49
i


4.

. .NET Framework ............51

4.1.

_______________________________________ 51

4.2.

.NET Framework _____________________________ 54

4.3.

XmlSerializer ___________________________________ 56

4.4.

SoapFormatter BinaryFormatter __________________ 67

4.5.

______________________ 71

5.

Microsoft Message Queuing (MSMQ)

...........................................................................................................................73
5.1.

MSMQ ________________________________ 73

5.2.

, MSMQ _______________ 75

5.3.

MSMQ ______ 77

5.4.

MSMQ .NET Framework __________ 80

5.5.

MSMQ __________________________________ 89

6.

COM+ Enterprise Services ...........................91

6.1.

COM+ _____________________________ 91

6.2.

COM+___________________________________________________ 93

...............................................................................................................93
..................................................................................................94
Just-in-time- ..........................................................................94
..........................................................................................95
..............................................................................................97
..............................................................................................98
............................................................................................99
6.3.

COM+ .NET Framework____________ 99

COM+ CLR ...............................................................99


........................................................................101
...................................................................104
..................................106
...................................................107
.................................................................116
COM+ COM+.......................................................................120
ii


6.4.
7.

Enterprise Services / COM+ ___________ 122


- ASP.NET ......................................................................................125

7.1.

- ___________________________________________ 125

7.2.

WSE ___________________________________ 128

7.3.

- .NET Framework _______________________ 130

- ..................................................................................................130
- ..............................................................................132
7.4.

WSE ________________________ 133

7.5.

________________________________ 138

7.6.

- _______________________________ 148

8.

.NET Remoting .......................................................................................150

8.1.

.NET Remoting ___________________________________ 150

8.2.

.NET Remoting _________________________________ 152

8.3.

.NET Remoting ____________________________ 156

8.4.

- .NET Remoting ______________________________________ 160

8.5.

Remoting ____________________________________________ 163

8.6.

___________________________________ 170

8.7.

.NET Remoting ___________________________ 178

9.

.NET Framework ....181

9.1.

_______________________________ 181

9.2.

______________________________ 183

..........................................................................................183
Kerberos........................................................................................................186
9.3.

.NET Framework___________________ 187

9.4.

_______________________ 189

10.

.................................................................190

10.1.

__________________________________ 190

10.2.

______________ 191

10.3.

.NET Framework _________ 194

iii


..................................................................................195
I. COM+ .......................................................196
II. ASP.NET IIS..............................................................199
III. ....................................................................204

iv


, . , , s_gorin@mail.ru.
, ..., . , ,
mstu@sevik.ru.


1. Microsoft .NET Framework 2.0
2. Microsoft Windows XP Pro SP2, Microsoft
Server 2003,
MSMQ, COM+ IIS

Microsoft Corporation SE Contest 2006.


Microsoft Microsoft Windows
Microsoft Corporation, .
.


, .
,

.

, ,
C/++.
, Microsoft,
(Common Language Infrastructure, CLI),
.NET,
. Microsoft .NET
Framework ,
:
(messaging queues), COM+, .NET Remoting, - (web services).
,
.

,
.
.
1. ,
.
2. ,
Microsoft .NET, .
3.
, .
2


.
Microsoft.NET Framework,
C#, TCP/IP,
, .
( 2006 )
.NET .
.

1.

1.
,
. .
.

1.1.

. ,

. ,
, ,
,
. , ,
,
(single point of failure).

.
,
. . ,

,
.
.
,

,

. , ,
.

1.

-, ()
, ().
(. 1.1).

1.1. -
- ,
, ,

.
.
, .

1.2.
,
(. 1.2):
5

1.
(), () (),
().
, ,
, ,
.

,

, ,
,
. ,
, (. 1.3).

1.3.

- .

.
- ,
,
6

1.
,
(. 1.4).

1.4.

, .
,
.

1.5.

1.

,
,
. ,
,
, ,
( 1.5).
,
,
.

(peer-to-peer networks).
,
, . 1.6.
,

1.6.

1.
1.2.


. , ,
, ,
.
, , .
.
,
,
, ,
, .

.

1.7.
9

1.
CLI,

(application domain),
.
,
. ,
,

(. 1.7).
.
, .

.
.

.

. ,

, -
.
1.3.

. ,

.
10

1.
.
.

.
.
.
,
.
.
.

, (load balancing)
.
, .

,
. ,
, , .
.



.
,
.
. , ,
,
. , ,
, .

11

1.
.
,
.
, ,
,
. ,
,
.

,
.
TCP/IP.
(unix sockets) POSIX-
(named pipes).
,
. ,
,
. ,
. ,
,
,
.
, : ,
, ,

,
.

.

,
12

1.
IP- (DNS).
,
(. 1.8).

DNS-

1.8. DNS
(, w3c.org)
.
.
, ,
. , (
.org), , ,
.
.

.
,
. , -

13

1.
.
, , .
1.4.

,
.

OSI/ISO,
: , , , ,
, , .
1

1.9.
TCP/IP TCP
, IP .

,
14

1.
.
.

TCP/IP ,
SSL/TLS.
TCP/IP ,
,
.


(middleware),
(. 1.9).
,
.
. :

: ,
;


(. 1.10).

,
,
.

15

1.

1.10.
,
, , ,
.

,
, .
,
, .

,
:
, , ,
, .

,
, .
16

1.

,
, .
, , ,

.

17

3.

2.

.
.
.

2.1.


.

:
.

TCP/IP,

,
. TCP HTTP

.
,
,
.
- ,
TCP/IP,
. ,
, ,
, , ,
. ,
, ,
18

3.

.
2.2.


.
, ,
.
.
,
.
.

, -
.
,

.
,
.

,
. , , Microsoft Message
Queuing, IBM MQSeries Sun Java System Message Queue.

,
;

;
19

3.

, .

,
.

, .

,
, ,
(. 2.1).

2.1.
.
:


,
.

;
20

3.

:
, .

2.3.

(remote procedure call, RPC)


80- ,
,
.
,
- (stub), .
-
, ,
.

(. 2.2).
.

2.2.
21

3.
.
1. :
;
2. : ,
,
(, , ).
: ,
,

callback-,

.
(
.NET)
(marshaling). -

. ,
.

(marshal by value),
.
,
.
.
,
.
,
.

22

3.
2.4.


(remote
method invocation, RMI). ,
.
. ,
,
. ,
,
.

.
, ,
, (proxy).
, .
, ,
.
, (skeleton) ,
, (. 2.3).
. ,
,
, .

(marshal by reference). ,
,
.
,
.

23

3.

Cc

2.3.
,
, .
, . -,

(exceptions) ,

,
, .
-,
( 2.4),
RMI.

24

3.

2.4. ,


:

:
,

: .


(singlecall), (singleton),
(client activation).
(server activation), , ,
- .

25

3.


.
,

. ,
.
,
.
(. 2.5).

2.5.

,

. ,

.

, ,
,
26

3.
, .
, , (object
pooling).
, ,
.

. ,
,
.

,

.


. ,
(. 2.6).

2.6.
.
27

3.

.
,
- .
,
.

(, )
, ,
.
,
,
(. 2.7).

2.7. , .


:


(stateless components);

28

3.

,
(statefull components).


, .
- ,
,
.

,

,
,
.
,

.
,


.

,
.
processing.FirstName = "";
processing.SecondName = "";
processing.ThirdName = "";
processing.City = "";
result = processing.Run();

29

3.
processing , Run()
. , processing
. , , .
1. ,
(set C#).
Run (
) ( ).
2. ,
. ,
,
. .
3. ,
,
(
).
,
,
4. .
,
.
,
,
.
,

.
.
.
30

3.
( chunky design)
, .
result = processing.Run("", "", "", "");

, ,

. : ,
, , .
,
,
.
person.FirstName = "";
person.SecondName = "";
person.ThirdName = "";
person.City = "";
result = processing.Run(person);


.
,
.
.
task.Epsilon = 1e-5:
task.X1 = -1;
task.X2 = 1;
task.MaximumSteps = 20;
task.Function += X2Function;
result = processing.Run(processingArguments);
...
double X2Function(double x)
{
return x*x;
}

processing , , ,
X2Function.
-,
, -, ,
.
31

3.

(, , )
.
,

, .NET Framework
.

C#.
2.5.


- , ,
.
,
.
.
. , ,
, ,
:

,
()
().
, -
, ( 2.8).

32

3.

2.8.
,
.

.
2.6.

- ,

(
). .

. .

.
,
.

. ,
.
,
, .

.
(.. ).

33

3.

2.9.
, ,

. ,
,
(. 2.9).

.
- , ,
, .
. :

-
, .

.
,
( )
,
.
34

3.
(compensating resource manager).
.
,
(business
activity) .
, , :
.
( , ,
). ,
,
(, ).
(,
) .
2.7.


,
.
1.

(1). ,
, ,
.
2.
().
,
(role-based security).

authentication identification.

35

3.
,
,

.
3. , ,
.

, .
,
, , .
2.8.

Microsoft .NET Framework

,
, 90- ,
,
. CLR

. .NET Framework
.
.NET Framework Class Library
.
.

Microsoft Message Queuing (MSMQ)


.

Microsoft Enterprise Services


Microsoft COM+,
.

ASP .NET Web Services


, XML.
36

3.

.NET Remoting
.

.NET Framework 3.0 WCF (Windows


Communication Foundation),
. , .NET Framework
, , XML-RPC
.

37

3.

3.

,
, .
.

3.1.


.

,
. ,
, .NET Framework,
:

,
;

-,

.

.

.
,
. HTTP, TCP, NetBIOS,
.
.
,
-.
,
38

3.
, , ,
.
- ,
,
(
-).
,
, .
-
,

-.

. ,

(
).

. ,
, ,
- . ,

CLI.
.
,

,
.
, ,

39

3.
.
.
, .
, :

();

().


(. 3.1).

3.1.

:

, .


.

,
.
.NET.
40

3.
,

, .NET Framework.
, ,

,
.

.
3.2.

XML XML

XML (Extensible Markup Language)



. . 3.2
, XML XSD, SOAP, WSDL,
.
XML:

XSD:

WSDL:

SOAP:

3.2. XML
XML ,
, .
,
41

3.

().

XML

- . XML

.
. ,
, ,
,
.
<?xml version="1.0" encoding="utf-8"?>
<GeomFigures>
<Point X="2" Y="-1" />
<Line>
<A X="-1" Y="-1" />
<B X="2" Y="2" />
</Line>
</GeomFigures>

XML
, ,
,
XML .
XML
, XML-DigitalSignature
XML-Encrypton,

XML

. XML- ,
XML- .
XML-
XML (XML namespace),
. URI
(Uniform Resource Identifier), ,
. URI
, . XML-

xmlns:schema_id.
42

3.
schema_id,
.

http://www.w3.org/2001/XMLSchema xs,
xs:schema.
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

,
.
.
XML .
XML ,
XML-. DTD (Document
Type Definition),
XML (XML Schema Definition, XSD). XSD-

XML,

http://www.w3.org/2001/XMLSchema. XML :

( );

http://www.w3.org/2001/XMLSchema.
, , ,
,
. ,
XML ( ),
. .NET
Framework xsd.exe, ,
. .NET
. ,
xsd.exe

XML.
43

3.
3.3.

SOAP:

XML
,
, . 90-

SOAP XML-RPC. XML-RPC
,
.NET Framework.
HTTP
,
,
. , SOAP
- , SOAP
WSDL - (web services).

SOAP

( SOAP 1.1 http://schemas.xmlsoap.org/soap/envelope/,


1.2 http://schemas.xmlsoap.org/wsdl/soap12/)
WSDL ( http://schemas.xmlsoap.org/wsdl/).
SOAP
Simple Object Access Protocol.
SOAP XML-,
(envelope), soap:Header
soap:Body.
, . ,
, SOAP
,
.
,

44

3.
SOAP SOAP-RPC ( ) SOAP-Document.
SOAP-RPC
.

SOAP-Document,

, XML-
, WSDL.

, -
.
SOAP 1.2 ,

http://summa.test/webservices, ,
. message .
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Body>
<Add xmlns="http://summa.test/webservices">
<message>
<a>1</a>
<b>2</b>
</message>
</Add>
</soap12:Body>
</soap12:Envelope>

.
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Body>
<AddResponse xmlns="http://summa.test/webservices">
<AddResult>3</AddResult>
</AddResponse>
</soap12:Body>
</soap12:Envelope>

3.4.

WSDL:

,
, WSDL (Web Service Definition Language).
WSDL (. 3.3).
45

3.

3.3. WSDL-
1.

SOAP-Document XML, ,
SOAP.
2. ,
.
3. ( ),
.
4. ( ),
.
5. (binding),
, SOAP.
6. ,
URL.
7. ( )
.
WSDL ,
.
46

3.

SOAP 1.2 http://schemas.xmlsoap.org/wsdl/soap12/.


<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions
xmlns:tns="http://summa.test/webservices"
xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
targetNamespace="http://summa.test/webservices"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">

wsdl:types . Add

, AddResponse
.
<wsdl:types>
<s:schema elementFormDefault="qualified"
targetNamespace="http://summa.test/webservices">
<s:element name="Add">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="message"
type="tns:AddMessage" />
</s:sequence>
</s:complexType>
</s:element>
<s:complexType name="AddMessage">
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="a" type="s:int" />
<s:element minOccurs="1" maxOccurs="1" name="b" type="s:int" />
</s:sequence>
</s:complexType>
<s:element name="AddResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="AddResult" type="s:int" />
</s:sequence>
</s:complexType>
</s:element>

SumList SumListResponse
.
<s:element name="SumList">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="list"
type="tns:ArrayOfInt" />
</s:sequence>
</s:complexType>
</s:element>

47

3.
<s:complexType name="ArrayOfInt">
<s:sequence>
<s:element minOccurs="0" maxOccurs="unbounded" name="int" type="s:int" />
</s:sequence>
</s:complexType>
<s:element name="SumListResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="SumListResult"
type="s:int" />
</s:sequence>
</s:complexType>
</s:element>
</s:schema>
</wsdl:types>

wsdl:message .
<wsdl:message name="AddSoapIn">
<wsdl:part name="parameters" element="tns:Add" />
</wsdl:message>
<wsdl:message name="AddSoapOut">
<wsdl:part name="parameters" element="tns:AddResponse" />
</wsdl:message>
<wsdl:message name="SumListSoapIn">
<wsdl:part name="parameters" element="tns:SumList" />
</wsdl:message>
<wsdl:message name="SumListSoapOut">
<wsdl:part name="parameters" element="tns:SumListResponse" />
</wsdl:message>

wsdl:portType
.
<wsdl:portType name="MathServiceSoap">
<wsdl:operation name="Add">
<wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
Add
</wsdl:documentation>
<wsdl:input message="tns:AddSoapIn" />
<wsdl:output message="tns:AddSoapOut" />
</wsdl:operation>
<wsdl:operation name="SumList">
<wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
SumList
</wsdl:documentation>
<wsdl:input message="tns:SumListSoapIn" />
<wsdl:output message="tns:SumListSoapOut" />
</wsdl:operation>
</wsdl:portType>

wsdl:binding (HTTP),
SOAP (1.2) (SOAP-Document).

48

3.
<wsdl:binding name="MathServiceSoap12" type="tns:MathServiceSoap">
<soap12:binding transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="Add">
<soap12:operation soapAction="http://summa.test/webservices/Add"
style="document" />
<wsdl:input>
<soap12:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap12:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="SumList">
<soap12:operation soapAction="http://summa.test/webservices/SumList"
style="document" />
<wsdl:input>
<soap12:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap12:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>

wsdl:service
, , URL,
-.
<wsdl:service name="MathService">
<wsdl:port name="MathServiceSoap12" binding="tns:MathServiceSoap12">
<soap12:address location="http://summa.test/webservices/summa.asmx" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>

, WSDL
,
,
, SOAP.

WSDL- ,
WSDL- .
3.5.

.

49

3.
: XML, XSD, SOAP WSDL.
, -
.

SOAP

,
, SOAP.
WSDL
SOAP .

50

4. . .NET Framework

4. .
.NET Framework

. ,
.
, .NET Framework, .

4.1.

, .NET Framework
,
,
.

CLR.


.
,
(,
, ) -,
,
( 4.1). ,
, .
1

4.1.
51

4. . .NET Framework

- ( System.ValueType) ,
.
.
, , ,
, (object graph).
-,
.
G = < V, E > ,
( V), , ,
( 4.2).
public class SampleClass
{
public SampleClass fieldA = null;
public SampleClass fieldB = null;
}
...
SampleClass root = new SampleClass();
SampleClass child1 = new SampleClass();
SampleClass child2 = new SampleClass();
root.fieldA = child1;
root.fieldB = child2;
child1.fieldA = child2;
...

root

child 1

child 2

4.2.
B A < A, B >
E.

- ,
. ,
CLI .

52

4. . .NET Framework
,
.
, .
.
, , ,
, , .
,
-


.
, < A, B1>, ... < A, Bn >, S
A S(A) = < V(A), <S(B1), ... S(Bn)>>, V
- .
,
( < A1, B>
< A2, B >). A ... A.

, ,
,
. A1, ... An ,
{< idA1, S(A1) >, ... <idAn, S(An) >},
S(A) S(A) = < V(A), <idB1, ... idBn> >, B1, ... Bn ,
A.
,

.
, ,
.

53

4. . .NET Framework
, XML,

.
, ,
, .
, -
.
4.2.

.NET Framework

Microsoft .NET Framework 2.0

Message Queuing, Enterprise Services, Remoting, Web services.


,
.
(MSMQ)
( ).
,
.
, .NET Framework,
(formatters).
ActiveXMessageFormatter, .NET Framework
: XmlSerializer, SoapFormatter, BinaryFormatter.
-,
:

- ASP.NET XmlSerializer;

Remoting SoapFormatter, BinaryFormatter


;

MSMQ

XmlSerializer

XMLMessageFormatter), BinaryFormatter ( BinaryMessageFormatter),


;

Enterprise

Services

Remoting

BinaryFormatter.
54

4. . .NET Framework

.
1. :

: ;

2. :

, ,
;

, XML ,

.

3. ,
:

:
, ;
,

;

:
, XSD.

XmlSerializer

, BinaryFormatter ,
SoapFormatter .
, BinaryFormatter, ,
. .

55

4. . .NET Framework
4.3.

XmlSerializer

System.Xml.Serialization.XmlSerializer
, XML
XML .
, , - ASP.NET
MSMQ. XmlSerializer
XML, .
XmlSerializer XML
.
, XmlSerializer ,
,
.
XML ,
, . ,
(generic) XML-
.
. , IVehicle vehicleValue
, IVehicle.
CLI

System.XML.Serialization.XmlAttrbute,

- ,

XML-.

XmlAttrbuteAttrbute.
[System.XML.Serialization.XmlAttrbute(typeof(Car)),
System.XML.Serialization.XmlAttrbute(typeof(Bike)),
System.XML.Serialization.XmlAttrbute(typeof(LongTruck))]
IVehicle vehicleValue;

, ,
CLI XML,
.
56

4. . .NET Framework
XmlSerializer .
-, :
. -, ,
.
,
( 4.3). XML-
- , , ,
, ,

- .

root

child 1

root

child 2

child 2

child 1

child 2

4.3. XmlSerializer

XmlSerializer

. .NET Framework 2.0


XmlSerializer ,
public .
1. IXMLSerializable. XMLSerializer
GetSchema, ReadXml, WriteXml.
2. System.Collections.IEnumerable,
ICollection Add c ,
,

IEnumerator.Current

GetEnumerator .
57

4. . .NET Framework
IEnumerator, GetEnumerator,
.
3.

System.Collections.ICollection,

IEnumerable. Item
, ICollection.
.
4. ICollection IEnumerable,
Item c Count.
, Add, Item
. .
5. IXMLSerializer, IEnumerable, ICollection
System.SerializableAttribute.
,
.

, get set. ,
,
, .
//
public int[,] data = new int[2,2];

58

4. . .NET Framework
, FCL, IDictionary,
( Add ).
XmlSerializer ,
System.Collections.IDictionary,

System.Collections.Hashtable. ,
Hashtable IXmlSerializable. XMLSerializer
FCL:

System.XML.XmlNode

System.XML.XmlDocumnt

System.XML.XmlElement, XML-
XML- ( ,
);

System.Data.Dataset;

(generic classes) System.Collections.Generic, List


Queue, Dictionary SortedDictionary.

,
System.Xml.Serialization ,
XML, .
NonSerializedAttribute ,
.
,
IXMLSerializable -
.
, .

59

4. . .NET Framework
using System.Xml;
using System.Collections;
using System.Xml.Serialization;
public class DictionaryCollection<TValue> : DictionaryBase, IXmlSerializable
{
private XmlSerializer valueSerializer;
private XmlSerializer keySerializer;
public DictionaryCollection()
{
keySerializer = new XmlSerializer(typeof(String));
valueSerializer = new XmlSerializer(typeof(TValue));
}

,
, .
public TValue this[string key]
{
get { return (TValue)this.Dictionary[key]; }
set { this.Dictionary[key] = value; }
}
public void Add(String key, TValue value)
{
this.Dictionary.Add(key, value);
}

XMLSerializer WriteXml
ReadXML.
public void WriteXml(System.Xml.XmlWriter writer)
{
foreach (String key in this.Dictionary.Keys)
{
keySerializer.Serialize(writer, key);
valueSerializer.Serialize(writer, this[key]);
}
}
public void ReadXml(System.Xml.XmlReader reader)
{
reader.Read();
while (reader.NodeType != XmlNodeType.EndElement)
{
String key = (String) keySerializer.Deserialize(reader);
TValue value = (TValue) valueSerializer.Deserialize(reader);
reader.MoveToContent();
Add(key, value);
}
}

60

4. . .NET Framework
GetSchema XSD- .
, .
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
} // DictionaryCollection<TValue>

,
- .
DictionaryCollection<Int32> dictionary = new DictionaryCollection<Int32>();
XmlSerializer serializer = new XmlSerializer(typeof(DictionaryCollection<Int32>));
dictionary.Add("key1", 10);
dictionary.Add("key2", 20);
using (StreamWriter writer = new StreamWriter("sample.xml"))
{
XmlTextWriter xmlWriter = new XmlTextWriter(writer);
xmlWriter.Formatting = Formatting.Indented;
serializer.Serialize(xmlWriter, dictionary);
}

IXmlSerializable,

System.Xml.Serialization, XML-. , ,

XmlAttributeAttribute,

XmlArrayItemAttribute,

XmlElementAttribute,

XmlIgnoreAttribute.

XmlArrayAttribute,

, .
XmlAttributeAttribute XmlElementAttribute
. XML
, . XmlElementAttribute
. ,
, , XML-
xsi:type .
XmlArrayAttribute, XmlArrayItemAttribute
. , (, ArrayList)
(, List<T>). XmlArray
61

4. . .NET Framework
XmlAttribute , XmlArrayItem

XML. XmlArrayItem
, .
, ,
. , List<Person> persons
Person, XmlArrayItem .

.
// figures.cs
using System;
using System.IO;
using System.Xml.Serialization;
using System.Collections.Generic;
public abstract class GeomFigure
{
}

,
. .

62

4. . .NET Framework
public class GeomPoint: GeomFigure
{
private double xField, yField;
[XmlAttribute("X")]
public double X
{
get {return xField;}
set {xField = value;}
}
[XmlAttribute("Y")]
public double Y
{
get {return yField;}
set {yField = value;}
}
public GeomPoint()
{
}
public GeomPoint(double x, double y)
{
this.X = x;
this.Y = y;
}
public override string ToString()
{
return String.Format("({0}, {1})", X, Y);
}
}
public class GeomLine: GeomFigure
{
private GeomPoint aField, bField;
public GeomPoint A
{
get {return aField;}
set {aField = value;}
}
public GeomPoint B
{
get {return bField;}
set {bField = value;}
}
public GeomLine()
{
}
public GeomLine(GeomPoint a, GeomPoint b)
{
this.A = a;
this.B = b;
}

63

4. . .NET Framework
public override string ToString()
{
return String.Format("{0} {1}", A, B);
}
}

XmlArrayItem
.
public class GeomFigures
{
private List<GeomFigure> figuresField;
[XmlArrayItem("Point", typeof(GeomPoint)),
XmlArrayItem("Line", typeof(GeomLine))]
public List<GeomFigure> Figures
{
get { return figuresField;}
}
public GeomFigures()
{
figuresField = new List<GeomFigure>();
}
}
public class App
{
public static void Main()
{
GeomFigures figures = new GeomFigures();
figures.Figures.Add(new GeomPoint(2, -1));
figures.Figures.Add(new GeomLine(new GeomPoint(-1, -1),
new GeomPoint(2, 2)));
XmlSerializer serializer = new XmlSerializer(typeof(GeomFigures));
using (StreamWriter writer = new StreamWriter("figures.xml"))
{
serializer.Serialize(writer, figures);
};
}
}

XML-.
<?xml version="1.0" encoding="utf-8"?>
<GeomFigures xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Figures>
<Point X="2" Y="-1" />
<Line>
<A X="-1" Y="-1" />
<B X="2" Y="2" />
</Line>
</Figures>
</GeomFigures>

64

4. . .NET Framework
,
XSD- .
.NET Framework xsd.exe, :

(partial) # XSD;

XSD #;

XSD XML- (
).

,
schema0.xsd XML.
xsd.exe figures.exe /type:GeomFigures

.
<?xml version="1.0" encoding="utf-8"?>
<xs:schema elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="GeomFigures" nillable="true" type="GeomFigures" />
<xs:complexType name="GeomFigures">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" name="Figures" type="ArrayOfChoice1" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="ArrayOfChoice1">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element minOccurs="1" maxOccurs="1" name="Point" nillable="true"
type="GeomPoint" />
<xs:element minOccurs="1" maxOccurs="1" name="Line" nillable="true"
type="GeomLine" />
</xs:choice>
</xs:complexType>
<xs:complexType name="GeomPoint">
<xs:complexContent mixed="false">
<xs:extension base="GeomFigure">
<xs:attribute name="X" type="xs:double" use="required" />
<xs:attribute name="Y" type="xs:double" use="required" />
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="GeomFigure" abstract="true" />
<xs:complexType name="GeomLine">
<xs:complexContent mixed="false">
<xs:extension base="GeomFigure">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" name="A" type="GeomPoint" />
<xs:element minOccurs="0" maxOccurs="1" name="B" type="GeomPoint" />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>

65

4. . .NET Framework
XML- C#,

XML- .
xsd.exe schema0.xsd /classes

,
XmlSerializer
, C#
XSD-. 4.4
XML- .
XMLSerializer XML
, ,
WSDL.
1

XML

4.4. XML
XMLSerializer ,

. ,
GeomFigures.XmlSerializers,
.
(,
,
66

4. . .NET Framework
), sgen.exe
.
XMLSerializer, ,
,

XSD. XMLSerializer

XmlDocument

Dataset,

XML- .

,
XML- . XmlSerializer
,
.
4.4.

SoapFormatter BinaryFormatter

System.Runtime.Serialization.Formatters.Soap.SoapFormatter

.NET

Remoting,

System.Runtime.Serialization.Formatters.Binary.BinaryFormatter

MSMQ XMLSerializer.
.
BinaryFormatter

SoapFormatter ,
SOAP-RPC ( http://schemas.xmlsoap.org/soap/encoding/).
.NET Framework 2.0

SoapFormatter

SoapFormatter


(generic types).

( ), . ,
System.NonSerializeAttribute,

67

4. . .NET Framework
System.SerializableAttribute.
System.Runtime.Serialization.FormatterServices.
,
.
ISerializable,
GetObjectData(SerializationInfo info, StreamingContext context)
, FormatterServices.

ISerializable(SerializationInfo info, StreamingContext context),


info.
,

System.Runtime.Serialization.IDeserializationCallback

OnDeserialization.

SerializationInf .
, IFormatter,
, .
ISerializable
.
using
using
using
using
using
using

System;
System.IO;
System.Runtime.Serialization;
System.Runtime.Serialization.Formatters;
System.Runtime.Serialization.Formatters.Binary;
System.Reflection;

[Serializable]
public class Person : ISerializable
{
public String name;
public Person()
{
}

68

4. . .NET Framework
GetObjectData .

SerializationInfo ,

.
GetSerializableMembers FormatterServices.
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
Type thisType = this.GetType();
MemberInfo[] serializableMembers =
FormatterServices.GetSerializableMembers(thisType, context);
foreach (MemberInfo serializableMember in serializableMembers)
{
// NonSerializedAttribute
if (!(Attribute.IsDefined(serializableMember,
typeof(NonSerializedAttribute))))
{
info.AddValue(serializableMember.Name,
((FieldInfo)serializableMember).GetValue(this));
}
}
}

SerializationInfo.
protected Person(SerializationInfo info,
StreamingContext context)
{
Type thisType = this.GetType();
MemberInfo[] serializableMembers =
FormatterServices.GetSerializableMembers(thisType, context);
foreach (MemberInfo serializableMember in serializableMembers)
{
FieldInfo fieldInformation = (FieldInfo)serializableMember;
if (!(Attribute.IsDefined(serializableMember,
typeof(NonSerializedAttribute))))
{
fieldInformation.SetValue(this,
info.GetValue(fieldInformation.Name,
fieldInformation.FieldType));
}
}
}
} // Person

Person.
public class SampleApp
{
public static void Main()
{
using (Stream stream = new MemoryStream())
{
IFormatter formatter = new BinaryFormatter();

69

4. . .NET Framework
Person person = new Person();
person.name = "";
Console.WriteLine(": {0}", person.name);
formatter.Serialize(stream, person);
stream.Position = 0;
Person personRestored = (Person) formatter.Deserialize(stream);
Console.WriteLine(": {0}", personRestored.name);
}
}
}

,
.
,

.
,
, ,
.
SurrogateSelector ,
System.Runtime.Serialization.ISurrogateSelector.

. .NET Remoting ,
MarshalByRefObject .
BinaryFormatter MSMQ MarshalByRefObject
,
BinarryMessageFormatter MarshalByRefObject
SurrogateSelector.

BinaryFormatter

, .
,
.

CLI,
.
,
CLI.
70

4. . .NET Framework
XML.

System.Xml.XmlDocument

BinaryFormatter SoapFormatter,
Serializable.
XmlDocument , .
XmlDocument,
ISerializable.
,
XmlDocument .
XmlDocument.ToString() XML-
, LoadXml, StringWriter.
// SevaXmlUtils.cs
using System;
using System.IO;
using System.Xml;
namespace Seva.Xml
{
public static class XmlUtils
{
public static String XmlToString(XmlDocument xml)
{
StringWriter xmlLine = new StringWriter();
xml.Save(xmlLine);
return xmlLine.ToString();
}
public static XmlDocument XmlFromString(String xmlLine)
{
XmlDocument xml = new XmlDocument();
xml.LoadXml(xmlLine);
return xml;
}
}
}

4.5.

.NET Framework
,
.
(
-, - ),
. , ,
71

4. . .NET Framework
( System.Data.Dataset) XML ( System.Xml.XMLDocument).
,
.

72

5. MSMQ

5. Microsoft Message Queuing (MSMQ)



5.1.

MSMQ


.
,
MSMQ, Sun Java System Message Queue, IBM MQSeries, Oracle Advanced Queing.
MSMQ Microsoft
,
Windows NT. MSMQ 3.0,
Windows XP PE 2003 Server, 2.0,
Windows 2000.
MSMQ
, .
, MSMQ, :

, .

, ,
(2 MSMQ 2.0).

MSMQ

2.0/3.0

.NET Framework.

73

5. MSMQ
MSMQ
, .

. MSMQ ,
. :

(
);

,
;

MSMQ ,
( MSMQ 3.0).



MSMQ

MSMQ

MSMQ
MSMQ

5.1. MSMQ
, MSMQ
( UDP)
, 5 .

, 5
74

5. MSMQ
,
MSMQ. ,
.
MSMQ
( 5.1).
, MSMQ ,

.
MSMQ
IBM IBM Websphere MQ ( MQSeries).
Websphere MQ .NET Framework,
, MSMQ,
MSMQ
Windows. MSMQ-MQSeries
,
IBM MQ .
.
Microsoft Message Queuing,
Microsoft Active Directory.
5.2.

, MSMQ

MSMQ Active Directory,


,
MSMQ, :

75

5. MSMQ
MSMQ (public) (private).
, ,
,
.
Active Directory.
ComputerName\QueueName,
.\QueueName .
.

MSMQ Active Directory.


, .
ComputerName\Private$\QueueName .\Private$\QueueName
. , ,

FCL.
MSMQ 3.0
HTTP Internet
Information Services (IIS).
http://domain.name/msmq/private$/queuename.
HTTP MSMQ, -
.

HTTP-

.
MSMQ (direct name)
(path name).
. MSMQ
.NET Framework :

Formatname:DIRECT=OS:server01\QueueName
server01;
76

5. MSMQ

Formatname:DIRECT=OS:ws02\Private$\QueueName
ws01;

Formatname:DIRECT=TCP:192.168.30.1\private$\QueueName

192.168.30.1.

, Windows RPC
( , 135- ). , MSMQ
NAT, HTTP-
.
5.3.

MSMQ

, MSMQ

.
1. . :
XML- XSD-,
. MSMQ .
2. . MSMQ Windows NT
(ACL) , AD
. , , MSMQ,
Active Directory.
3. . MSMQ ,
, .

,

77

5. MSMQ
4. . MSMQ ,
COM+ System.Transactions.
,
(, )
, .
COM+

System.Transactions

(MS DTC).
, ,
, .
, MSMQ
,
, MSMQ
. COM+
.
5. .

MSMQ

. ,

.
.
,
MSMQ .
.
1. ,
.
2. MSMQ LAN/VPN. -
HTTP
, VPN,
.

78

5. MSMQ
3. - MSMQ
.
, ,
,
.
.
(.\Private$\LocalQueueName)
(SomeComputer\Private$\RemoteQueueName).
MSMQ, ,
.

,
.
,
- ,
( ).
( -), , ,
.
,
.
,
. MSMQ
,
. MSMQ
:

( );


.
79

5. MSMQ
,
,
. , MSMQ
,
- , MSMQ
.NET Framework
,
.
,
,
( ).
MSMQ
, .
- ,
. , MSMQ
.NET Framework , ,
.

,
ICMP,
MSMQ .
,

.
5.4.

MSMQ .NET Framework


System.Messaging. System.Messaging.MessageQueue
.
1. : Create, Delete, Exists, Purge.
80

5. MSMQ
2. : GetPublicQueues, GetPublicQueuesByLabel
. ,
Active Directory,
.
3. (Send, Receive, Peek ),

(BeginPeek,

BeginReceive).
System.Messaging
:

, ;

, ,
MSMQ;

, ,
COM+.

MSMQ .NET Framework


. ,
,
,
.
,
.
MSMQ
XMLMessageFormatter
System.Messaging.

BinaryMessageFormatter
XMLMessageFormatter

System.Xml.Serialization.XmlSerializer, ,

XMLMessageFormatter

XmlSerializer. BinaryMessageFormatter
BinaryFormatter.

81

5. MSMQ
BinaryFormatter XmlSerializer
,
BinaryMessageFormatter XMLMessageFormatter

.

XMLMessageFormatter.

MSMQ

XSD-

. MSMQ
, BinaryMessageFormatter,
.
,
-
MSMQ ( 5.2).

MSMQ

5.2. MSMQ

System.Messaging .
using System;
using System.Messaging;
using System.Collections.Generic;

,
.
namespace Seva.Msmq
{
//
enum QueueType {NonTransactional, Transactional};
//
enum QueueFormatter {Binary, Xml};

82

5. MSMQ
//
delegate AnswerType ProcessRequestEventHandler
<RequestType, AnswerType>(Object sender, RequestType request,
MessageQueue queueResponse);
//
delegate void ProcessAnswerEventHandler<RequestType, AnswerType>
(Object sender, RequestType request, AnswerType answer);

MSMQUser, MSMQServer MSMQClient.


public abstract class MsmqUser
{
//
private bool recoverable = false;
public bool Recoverable
{
get {
return recoverable;
}
set {
recoverable = value;
}
}
//
protected IMessageFormatter requestFormatter;
protected IMessageFormatter answerFormatter;
//
public MsmqUser(QueueFormatter formatterType)
{
if (formatterType == QueueFormatter.Xml)
{
requestFormatter = new XmlMessageFormatter(
new Type[]{typeof(RequestType)});
answerFormatter = new XmlMessageFormatter(
new Type[]{typeof(AnswerType)});
}
if (formatterType == QueueFormatter.Binary)
{
requestFormatter = new BinaryMessageFormatter();
answerFormatter = new BinaryMessageFormatter();
}
}
}

, MSMQ .
class MsmqClient<RequestType, AnswerType> :
MsmqUser<RequestType, AnswerType>, IDisposable
{
//
private MessageQueue queueSend;
private MessageQueue queueReceive;
//
private Dictionary<String, RequestType> messages;
public Dictionary<String, RequestType> Messages
{
get { return messages;}
}

83

5. MSMQ
// ,
public event ProcessAnswerEventHandler<RequestType, AnswerType>
ProcessAnswer;

, .
public MsmqClient(String queueSendName, String queueReceiveName,
QueueFormatter formatterType): base(formatterType)
{
//
messages = new Dictionary<String,RequestType>();
// ,
queueSend = MsmqTools.CreateQueue(queueSendName,
QueueType.Transactional);
// ,
if (queueReceiveName != null)
{
queueReceive = MsmqTools.CreateQueue(queueReceiveName);
queueReceive.Formatter = answerFormatter;
// CorrelationId
queueReceive.MessageReadPropertyFilter.CorrelationId = true;
}
else
{
queueReceive = null;
}
}

Dispose .
public void Dispose()
{
queueSend.Close();
queueSend.Dispose();
if (queueReceive != null)
{
queueReceive.Close();
queueReceive.Dispose();
}
}

BeginReceive EndReceive ,
PeekComplete .
public void BeginReceive()
{
// ,
//
queueReceive.PeekCompleted += OnPeek;
//
queueReceive.BeginPeek();
}

84

5. MSMQ
//
public void EndReceive()
{
//
queueReceive.PeekCompleted -= OnPeek;
}

Send
. ,
ResponseQueue .
public void Send(RequestType request)
{
//
Message message = new Message(request, requestFormatter);
message.ResponseQueue = queueReceive;
//
message.Recoverable = Recoverable;
// ;
// , -
// MessageQueueTransactionType.Single
queueSend.Send(message, MessageQueueTransactionType.Single);
// message.Id ;
// c
//
messages.Add(message.Id, request);
}

PeekComplete MSMQ.

ProcessAnswer. ,
.
.
public void OnPeek(Object source, PeekCompletedEventArgs asyncResult)
{
// MSMQ
MessageQueueTransaction transaction = new MessageQueueTransaction();
//
transaction.Begin();
try
{
//
queueReceive.EndPeek(asyncResult.AsyncResult);
//
Message message = queueReceive.Receive(transaction);

85

5. MSMQ
// CorrelationId
//
String messageId = message.CorrelationId;
// ?
if (messages.ContainsKey(messageId))
{
if (message.Body is AnswerType)
{
//
//
AnswerType answer = (AnswerType) message.Body;
ProcessAnswer(this, messages[messageId], answer);
};
messages.Remove(messageId);
}
//
BeginReceive();
//
transaction.Commit();
}
catch (Exception e)
{
//
transaction.Abort();
throw e;
}
}
}

MSMQServer , MSMQ
.
class MsmqServer<RequestType, AnswerType>:
MsmqUser<RequestType, AnswerType>, IDisposable
{
//
private MessageQueue queueReceive;
// ,
public event ProcessRequestEventHandler<RequestType, AnswerType>
ProcessMessage;

.
public MsmqServer(String queueReceiveName, QueueFormatter formatterType):
base(formatterType)
{
// ,
queueReceive = MsmqTools.CreateQueue(queueReceiveName,
QueueType.Transactional);
queueReceive.Formatter = requestFormatter;
}

Dispose .

86

5. MSMQ
public void Dispose()
{
queueReceive.Close();
queueReceive.Dispose();
}

BeginReceive EndReceive ,
PeekComplete .
//
public void BeginReceive()
{
queueReceive.PeekCompleted += OnPeek;
queueReceive.BeginPeek();
}
//
public void EndReceive()
{
queueReceive.PeekCompleted -= OnPeek;
}

OnPeek PeekCompleted .

.
ProcessMessage. ResponseQueue
, .
// PeekCompleted
public void OnPeek(Object source, PeekCompletedEventArgs asyncResult)
{
// MSMQ
MessageQueueTransaction transaction = new MessageQueueTransaction();
//
transaction.Begin();
try
{
queueReceive.EndPeek(asyncResult.AsyncResult);
// c
Message message = queueReceive.Receive(transaction);
// ResponseQueue ,
//
MessageQueue queueResponse = message.ResponseQueue;
try
{
if (message.Body is RequestType)
{
RequestType request = (RequestType) message.Body;
//
AnswerType answer = ProcessMessage(this, request,
queueResponse);

87

5. MSMQ
if ((queueResponse != null) && (answer != null))
{
Message answerMessage = new Message(answer,
answerFormatter);
answerMessage.Label = "Answer";
answerMessage.CorrelationId = message.Id;
answerMessage.Recoverable = Recoverable;
//
queueResponse.Send(answerMessage, transaction);
}
}
}
finally
{
if (queueResponse != null)
{
queueResponse.Close();
queueResponse.Dispose();
}
};
//
BeginReceive();
//
transaction.Commit();
}
catch (Exception e)
{
//
Console.WriteLine(e);
transaction.Abort();
throw e;
}
}
}

MsmqTools
.
static class MsmqTools
{
static public MessageQueue CreateQueue(String queueName)
{
return CreateQueue(queueName, QueueType.Transactional);
}
//
static public MessageQueue CreateQueue(String queueName,
QueueType type)
{
MessageQueue messageQueue;

88

5. MSMQ

// ,
//
try
{
if (!MessageQueue.Exists(queueName))
{
MessageQueue.Create(queueName,
type == QueueType.Transactional);
}
}
catch(Exception)
{
}
MessageQueue messageQueue = new MessageQueue(queueName);
return messageQueue;

}
}

,
, .
queueName = @"Server\PublicQueue";


.
queueName = @"Formatname:DIRECT=OS:Computer\Private$\PrivateName";

.
5.5.

MSMQ

Microsoft Message Queuing

(MSMQ IBM MQ).


89

5. MSMQ
MSMQ
(queued components) COM+, ,
COM+. MSMQ
,
COM+ . ,
MSMQ .NET Remoting,
, .
, MSMQ ,

.

90

6. COM+

6. COM+
Enterprise Services
6.1.

COM+

COM+ ,
. Microsoft 90-
Microsoft Windows 2000.

COM+

.
COM+:

,
;

(distributed
transactions coordinator, DTC);

(roles),

COM+

COM+,

COM+. COM+,
, COM+.
COM+ .
COM+.
COM+ : .
,
, ,
.
COM+
COM+.
COM+
91

6. COM+
. (proxy) COM+
COM+,
COM+ , ,
.
COM+
,
,
COM+.
. 6.1 COM+
.

COM+

COM+,

.
COM+ (interceptor).

COM+

COM+

COM+

COM+

RPC

COM+

RPC

COM+

COM+
2

6.1. COM+
COM+

COM+,

92

6. COM+
.
, . , COM+
COM+
. COM+

comexp.msc , comadmin.dll.
I.
COM+
, COM+,
COM+.
.

COM+, .
6.2.

COM+

COM+
COM+ ,
. Windows 2003/XP SP2,
COM+,
.

COM+
.
COM+ .
COM+,
COM+,
, . COM+ ,
COM+
. ,
. COM+
( ), ,
93

6. COM+
COM+ ,
6.1.
6.1 COM+

COM+


(Not Supported)

(Supported)

(Required)


(Requires new)

,
, .

COM+ .
COM+ Microsoft
Windows (Windows 2000 Advanced Server ). COM+

COM+.
Windows Clustering
Services. , COM+

.
Just-in-time-
COM+
( COM+
JIT-)

94

6. COM+
,
.

COM+
.
COM+ .
, Not supported,
JIT-
Required Requires new. COM+
6.2
6.2 COM+

COM+


(Not Supported)

(Supported)

(Required)


(Requires new)

,
COM+
(. 6.2).
, ,
COM+.
, , MSMQ MS SQL.

.

95

6. COM+

COM+

ID

ID
COM+

6.2. COM+

. ,
, COM+

(. 6.3).

6.3. COM+

96

6. COM+

MSMQ COM+,

MSMQ
COM+, .
COM+
(queued componenets),

MSMQ.

(. 6.4).

COM+

MSMQ

COM+

6.4. COM+
1.
, (recorder),
.

97

6. COM+
2. ,
,

MSMQ

.
3. MSMQ (listener),
COM+ .
COM+ , (listener helper),
.
4. (player),
,
.
.

: ,
.
(call-back object),
,

MSMQ

(, ), (. 6.5).

6.5.

COM+

- COM+ ( ).
98

6. COM+
,
COM+, .
,
COM+.

COM+
. COM+

.
COM+ .
COM+,
,
. COM+
.

Microsoft Windows.

, COM+

CLI, COM+ .NET


Framework.
,
.
, . ,
,
, .
6.3.

COM+ .NET Framework

COM+ CLR
COM+ .NET,
CLR.
99

6. COM+
COM+ .NET Framework
COM+.
CLR COM+,
, COM+ (serviced
component), ( COM+) .
,
System.EnterpriseServices.ServicedComponent .
ServicedComponent
COM+. . 6.6.

.NET
Remoting

COM+

6.6. COM+ CLR


.NET Remoting (
BinaryFormatter), COM+
.

100

6. COM+
6.6, .NET Framework ,
, COM+. .NET
Enterpsise Services COM+,
COM+ .
, COM+
, ,
CLR COM+. ,

COM+, COM+
System.Runtime.InteropServices.COMException.
COM+,
, .
Unhandled Exception: System.Runtime.InteropServices.COMException (0x8000FFFF):
Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED))
Unhandled Exception: System.Runtime.InteropServices.COMException (0x8004D082):
Exception from HRESULT: 0x8004D082


.NET, , ,
.NET Remoting
, .NET
Remoting .

.NET Framework ,

System.EnterpriseServices.ServicedComponent,

public;

, , .

,
, COM+ , .
101

6. COM+
,
COM+.
public, .

System.EnterpriseServices, (TransactionAttribute),
(JustInTimeActivationAttribute
(SynchronizationAttribute).

ObjectPoolingAttribute)

JIT- ,
JIT- .
.
// SampleComponent.cs
using System;
using System.EnterpriseServices;
[assembly:
[assembly:
[assembly:
[assembly:

ApplicationAccessControl(false)]
ApplicationName("Serviced Component Example 01")]
Description("Sample of .NET serviced component.")]
ApplicationActivation(ActivationOption.Server)]

,
COM+. ApplicationActivation
.
namespace ServicedComponentSample
{
[JustInTimeActivation]
[Transaction(TransactionOption.Required)]
[ObjectPooling(Enabled=true, MinPoolSize=5, MaxPoolSize=10)]
public class SampleComponent: ServicedComponent
{

, ,
JIT-
public SampleComponent()
{
}


().
,
102

6. COM+
, -
.
Activate Deactivate, ,
.
protected override void Activate()
{
}
protected override void Deactivate()
{
//
//
}

CanBePooled true,
, .
protected override bool CanBePooled()
{
//
return true;
}

System.EnterpriseServices.AutoCompleteAttribute

. ,
, ,
.
[AutoComplete]
public void Do()
{
}
}
}
// SampleComponent.cs

AutoComplete
ContextUtil.
COM+, .
ContextUtil.SetComplete COM+ ,
ContextUtil.SetAbort .
.
103

6. COM+
try
{

...
ContextUtil.SetComplete();

}
catch()
{
ContextUtil.SetAbort();
}

ContextUtil ,
COM+ ,
COM+. ,
ContextUtil, , , AutoComplete,
.

, ,
COM+ COM+.
(strong-named assembly).
, .
, .
, .
sn.exe .NET
Framework

SDK.

SampleComponent.cs ( make-)
.
sn -k SampleComponent.snk
csc /target:library /r:System.EnterpriseServices.dll SampleComponent.cs
/keyfile:SampleComponent.snk

COM+.

.NET

Framework

System.EnterpriseServices.RegistrationHelper;

c regsvcs.exe;

.
104

6. COM+
.
.
regsvcs SampleComponent.dll

COM+ .
regsvcs /u SampleComponent.dll


.
// SampleClient.cs
using System;
using ServicedComponentSample;
class Test
{
static public void Main()
{
using(SampleComponent com = new SampleComponent())
{
com.Do();
}
}
}
// SampleClient.cs

using Dispose .

COM+.
.
csc /target:exe /r:SampleComponent.dll SampleClient.cs


SampleComponent.dll. ,
comexp.msc COM+,

SampleClient.exe. ,
COM+ ,
, .
105

6. COM+

.
,
,
.NET Remoting
BinaryFormatter. ,
,

System.Runtime.Serialization.Formatter.

FCL,

System.ApplicationException System.SystemException,
.

. ,

SoapFormatter

BinaryFormatter.

System.SystemException, .
// ComException.cs
using System;
using System.EnterpriseServices;
using System.Runtime.Serialization;
[assembly: ApplicationActivation(ActivationOption.Server)]
[assembly: ApplicationAccessControl(false)]
[Serializable]
public class CustomException: System.ApplicationException
{
public CustomException(SerializationInfo info, StreamingContext context):
base(info, context)
{
}
public CustomException(string message): base(message)
{
}
}
public class ComSample: ServicedComponent
{
public ComSample()
{
}
public void Process()
{
throw new CustomException(" ");
}
}

106

6. COM+
class MainApp
{
static public void Main()
{
ComSample com = new ComSample();
try
{
com.Process();
}
catch(CustomException e)
{
Console.WriteLine(": {0}", e.Message);
}
finally
{
com.Dispose();
}
}
} // ComException.cs

.
sn -k ComException.snk
csc ComException.cs /keyfile:ComException.snk /r:System.EnterpriseServices.dll
regsvcs ComException.exe



COM+ - , COM+.

System.EnterpriseServices.CompensatingResourceManager:

(log), ;

( Clerk), ;

( Compensator),

.


.
. ,
- , ,
,
. ,
107

6. COM+

.

. :


. .
,
. ,
,
.
( ) .
make-,
.NET SDK nmake.exe.
.
# : makefile
all: CrmSample.exe
#
CrmSample.key:
sn -k CrmSample.key
CrmSample.exe: CrmSample.cs CrmSample.Key
csc /r:System.EnterpriseServices.dll CrmSample.cs /keyfile:CrmSample.key
install:
# COM+
regsvcs CrmSample.exe
uninstall:
regsvcs u CrmSample.exe

COM+,
, sn.exe .NET SKD .
C# csc.exe , .
nmake install COM+
regsvcs.exe Microsoft Windows.
CrmSample.cs.
108

6. COM+
// CrmSample.cs
using System;
using System.IO;
using System.Collections.Generic;
using System.EnterpriseServices;
using System.EnterpriseServices.CompensatingResourceManager;
[assembly:
[assembly:
[assembly:
[assembly:
[assembly:

ApplicationActivation(ActivationOption.Server)]
ApplicationAccessControl(false)]
ApplicationCrmEnabled]
ApplicationName("Seva CRM")]
Description(" CRM")]

System.EnterpriseServices
COM+:

ApplicationActivation

COM+ (

);

ApplicationCrmEnabled CRM
COM+;

ApplicationAccessControl ,
;

System.ComponentModel.DescriptionAttribute .

StreamLog ,
.
public static class StreamLog
{
public static void Save(LogRecord log)
{
if (log.Record is object[])
{
object[] record = (object[])log.Record;
string fileName = (string) record[0];
byte[] buffer = (byte[]) record[1];
using (FileStream file = new FileStream(fileName,
FileMode.Create, FileAccess.Write))
{
file.Write(buffer, 0, buffer.Length);
}
}
} // Save()
} // StreamLog

StreamCache ,
.

109

6. COM+
public class StreamCache
{
private string fileName;
private MemoryStream stream;
public MemoryStream Stream
{
get { return stream;}
}
public string FileName
{
get { return fileName;}
}
public StreamCache(string streamFileName)
{
fileName = streamFileName;
stream = new MemoryStream();
}

Reopen .
MemoryStream,
, ,
.
public void Reopen()
{
if (!stream.CanRead)
{
stream.Close();
byte[] buffer = stream.ToArray();
stream.Dispose();
stream = new MemoryStream();
stream.Write(buffer, 0, buffer.Length);
stream.Seek(0, SeekOrigin.Begin);
}
} // Reopen()

Read,
MemoryStream.
public void Read()
{
byte[] buffer = new byte[32*1024];
using (Stream inputStream = new FileStream(fileName,
FileMode.Open, FileAccess.Read))
{

110

6. COM+
while (true)
{
int read = inputStream.Read(buffer, 0, buffer.Length);
if (read <= 0)
{
break;
}
Stream.Write(buffer, 0, read);
}
}
} // Read()
} // StreamCache

StreamCrm , COM+.
COM+ ,
COM+ .
.
public class StreamCrm: ServicedComponent
{
private Dictionary<string, StreamCache> cache;
public StreamCrm()
{
cache = new Dictionary<string, StreamCache>();
}

StreamCrm.CheckCache , .

,
StreamCache.Reopen.
private StreamCache CheckCache(string fileName, bool read)
{
StreamCache streamCache;
string key = Path.GetFullPath(fileName).ToLower();
if (!cache.ContainsKey(key))
{
streamCache = new StreamCache(fileName);
cache.Add(key, streamCache);
if (read)
{
streamCache.Read();
};
}
else
{
streamCache = cache[key];
streamCache.Reopen();
};
return streamCache;
}

111

6. COM+
StreamCrm.ReadFromFile , ,
StreamCrm.WriteToFile .
public MemoryStream ReadFromFile(string fileName)
{
return CheckCache(fileName, true).Stream;
}
public MemoryStream WriteToFile(String fileName)
{
return CheckCache(fileName, false).Stream;
}

StreamCrm.Flush ,

,
.
public object[] Flush(String fileName)
{
StreamCache streamCache = CheckCache(fileName, false);
streamCache.Stream.Close();
object[] record = new object[2];
record[0] = fileName;
record[1] = streamCache.Stream.ToArray();
return record;
}

StreamCrm.CreateClerk

.
.
public static Clerk CreateClerk()
{
return new Clerk(typeof(StreamCompensator), "Compensator",
CompensatorOptions.AllPhases);
}
}

StreamCompensator Compensator

.
public class StreamCompensator :
System.EnterpriseServices.CompensatingResourceManager.Compensator
{
private bool prepared = false;

112

6. COM+
c Prepare
. PrepareRecord false,

, PrepareRecord.
public override void BeginPrepare ()
{
}
public override bool PrepareRecord(LogRecord log)
{
prepared = false;
if (!(log.Record is object[]))
return true;
object[] record = log.Record as object[];
if (record.Length != 2)
return true;
if (!(record[0] is string) || !(record[1] is byte[]))
return true;
prepared = true;
return false;
}

EndPrepare .
true, .
public override bool EndPrepare ()
{
return prepared;
}

c Commit .
CommitRecord ,
.
public override void BeginCommit (bool commit)
{
}
public override bool CommitRecord (LogRecord log)
{
StreamLog.Save(log);
return true;
}
public override void EndCommit ()
{
}

Abort
.
113

6. COM+
,
.
public override void BeginAbort (bool abort)
{
}
public override bool AbortRecord (LogRecord log)
{
return true;
}
public override void EndAbort ()
{
}
} // StreamCrm

COM+,
. , COM+
. TransactionAttribute
COM+. SampleCrmClient2
ReadLine,
.
[Transaction(TransactionOption.Required)]
public class SampleCrmClient2: ServicedComponent
{
public SampleCrmClient2()
{
}
public string ReadLine(StreamCrm crm, string fileName)
{
using (StreamReader reader = new StreamReader(crm.ReadFromFile(fileName)))
{
return line = reader.ReadLine();
}
}
}

SampleCrmClient.DoSomeWork CRM.
, COM+
%systemroot%\system32.

114

6. COM+
[Transaction(TransactionOption.RequiresNew)]
public class SampleCrmClient1: ServicedComponent
{
public SampleCrmClient1()
{
}
public void DoSomeWork(string dir)
{
const string fileName1 = "sample1.txt";
const string fileName2 = "sample2.txt";
Environment.CurrentDirectory = dir;
StreamCrm crm = new StreamCrm();
Clerk clerk = StreamCrm.CreateClerk();

. ,
, .
,
StreamCrm.Flush. ,
.
using (StreamWriter writer = new StreamWriter(crm.WriteToFile(fileName1)))
{
writer.Write(Environment.CurrentDirectory);
}
//
clerk.WriteLogRecord(crm.Flush(fileName1));

COM+
SampleCrmClient2. ,
,
, , ,
.
String tempString = "";
using (SampleCrmClient2 client2 = new SampleCrmClient2())
{
tempString = client2.ReadLine(crm, Path.GetFullPath(fileName1));
}

.
using (StreamWriter writer = new StreamWriter(crm.WriteToFile(fileName2)))
{
writer.WriteLine(String.Format(" [{0}]:", fileName1));
writer.WriteLine(tempString);
}

115

6. COM+
//
clerk.WriteLogRecord(crm.Flush(fileName2));
// ,
ContextUtil.SetComplete();
}
}

CrmTest Main. try .. finally Dispose C#


using .

EnterpriseServices/COM+ Dispose (
using) .
class CrmTest
{
public static void Main()
{
SampleCrmClient1 client1 = new SampleCrmClient1();
try
{
client1.DoSomeWork(Environment.CurrentDirectory);
}
finally
{
client1.Dispose();
}
}
}

,
, ,
IDisposable
Dispose ( ) .

(. 6.7):

, ;

(event class),
, ;

;
COM+;
116

6. COM+

,
.

( )


COM+

COM+

6.7.
, -.

, .
// LceEvents.cs
using System;
using System.Runtime.InteropServices;
using System.EnterpriseServices;
public static class EventsGuids
{
public const string interfaceId = "A5105B2C-40BF-46C6-B19C-4286A423DBF9";
public const string eventClassId = "DF64D391-CCE9-4FC6-B5F2-3F4DE3FA48C2";
}
[Guid(EventsGuids.interfaceId)]
public interface ILceMessage
{
void TriggerEvent(string message);
}
// LceEvents.cs

, .

117

6. COM+
// LcePublisher.cs
using
using
using
using

System;
System.Threading;
System.Runtime.InteropServices;
System.EnterpriseServices;

[assembly: ApplicationName("LCE publisher")]


[assembly: ApplicationActivation(ActivationOption.Server)]
[assembly: ApplicationAccessControl(false)]

, EventClassAttribute
.
, .
[EventClass]
[Guid(EventsGuids.eventClassId)]
[Transaction(TransactionOption.Disabled)]
public class LceEvents: ServicedComponent, ILceMessage
{
public void TriggerEvent(string message)
{
}
}

,
COM+. ,
COM+.
public class LcePublisher: ServicedComponent
{
public LcePublisher()
{
}
public void DoWork()
{
ILceMessage lcEvent = (ILceMessage) new LceEvents();
try
{
while (true)
{
lcEvent.TriggerEvent("!");
Thread.Sleep(1000);
}
}
catch (System.Runtime.InteropServices.COMException)
{
Console.WriteLine(" ");
}
}
}

118

6. COM+
class MainApp
{
public static void Main()
{
LcePublisher com = new LcePublisher();
com.DoWork();
}
}
// LcePublisher.cs

COM+, .
.

, .
,
.
// LceSubscriber.cs
using System;
using System.IO;
using System.Threading;
using System.Runtime.InteropServices;
using System.EnterpriseServices;
using System.Messaging;
using Seva.ComUtils;
using Seva.Msmq;
[assembly: ApplicationName("LCE demo")]
[assembly: ApplicationActivation(ActivationOption.Server)]
[assembly: ApplicationAccessControl(false)]
public static class Consts
{
public const string testQueue = @".\Private$\sample_queue";
}
[JustInTimeActivation]
[Transaction(TransactionOption.Required)]
public class LceSubscriber : ServicedComponent, ILceMessage
{
public LceSubscriber()
{
}


,
.

119

6. COM+
public void TriggerEvent(string message)
{
MessageQueue queue = MsmqTools.CreateQueue(Consts.testQueue);
queue.Send(message, MessageQueueTransactionType.Automatic);
ContextUtil.SetComplete();
}
}
class MainApp
{
public static void Main()
{
//
//
LceSubscriber subscriber = new LceSubscriber();
//
LceUtils.PermanentSubscription(Consts.comAppName,
typeof(LceSubscriber).ToString(),
EventsGuids.eventClassId, EventsGuids.interfaceId);
}
}
// LceSubscriber.cs

Make- .
all: LceSubscriber.exe LcePublisher.exe
LceSubscriber.snk:
sn -k LceSubscriber.snk
LcePublisher.snk:
sn -k LcePublisher.snk
LceSubscriber.exe: Seva*.cs LceEvents.cs LceSubscriber.cs LceSubscriber.snk
csc /out:LceSubscriber.exe Seva*.cs LceEvents.cs LceSubscriber.cs
/r:interop.comadmin.dll /keyfile:LceSubscriber.snk
LcePublisher.exe: Seva*.cs LceEvents.cs LcePublisher.cs LcePublisher.snk
csc /out:LcePublisher.exe Seva*.cs LceEvents.cs LcePublisher.cs
/r:interop.comadmin.dll /keyfile:LcePublisher.snk

COM+ COM+
(SWC) COM+
COM+ ServicedComponent.
SWC TCP/IP
.
Windows 2003 Windows XP SP2, .
NAT, .
%systemroot%\system32\Com\comexp.msc
:
120

6. COM+
REGEDIT4
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSDTC\Security]
"NetworkDtcAccess"=dword:00000001


net stop MSDTC
net start MSDTC

, SWC. COM+
,
System.IDisposable void Dispose(),
COM+.
using System;
using System.EnterpriseServices;
namespace Seva.Swc
{
public class SwcUtil : IDisposable
{
public SwcUtil()
{
ServiceDomain.Enter(GetConfig(TransactionOption.Required));
}
public SwcUtil(TransactionOption transactionOption)
{
ServiceDomain.Enter(GetConfig(transactionOption));
}
protected virtual ServiceConfig GetConfig(
TransactionOption transactionOption)
{
ServiceConfig config = new ServiceConfig();
config.Transaction = transactionOption;
config.TrackingEnabled = true;
config.TrackingAppName = "SwcUtil";
config.TrackingComponentName = this.GetType().FullName;
}

return config;

public void Dispose()


{
ServiceDomain.Leave();
}
}
}

.
COM+.
121

6. COM+
using System;
using System.EnterpriseServices;
using System.Messaging;
using Seva.Msmq;
using Seva.Swc;
public class MainApp
{
public static void Main()
{
using (SwcUtil swc = new SwcUtil())
{
MessageQueue queue = MsmqTools.CreateQueue(@".\Private$\swc_queue");
queue.Send("SWC Message", MessageQueueTransactionType.Automatic);
Console.WriteLine(" <Enter> ");
Console.ReadLine();
ContextUtil.SetComplete();
}
}
}

SWC ,
COM+.
, SWC

-,

System.EnterpriseServices.ServicedComponent,

Compensator

, COM+.
Clerk
catastrophic exception,
, . ,
, ,
, MSMQ MS SQL.
6.4.

Enterprise Services / COM+

COM+
, .
1. COM+ .NET Framework, Enterprise Services
.NET Framework,
. Enterprise Services
122

6. COM+
,
CLR COM+.
2. COM+ ,
, , RPC (135-
TCP). , ,
.
COM+
.
1. . COM+ Microsoft
Windows 2000
Windows.

COM+. , Enterprise Services .
2. . COM+
Windows Server.
,
JIT-. COM+
,
.
3. . COM+
Microsoft (MTS)
.
4. . COM+
(DNS NETBIOS), COM+.
, (
COM+).

Windows

Clustering,

,
123

6. COM+
. , COM+
.
5. ( ). COM+ .Net
,
.
6. . COM+
Microsoft Windows.
, EnterpriseServices/COM+
,

, Microsoft Windows
.

124

7. - ASP.NET

7. - ASP.NET
7.1.

- - (web service, WS) ,


WS-I (Web
Services

Interoperability),

SOAP, WSDL, HTTP


, XML XML.
- XML
SOAP-Document.
ASP.NET
. ASP.NET WSDL- -
.NET,
SOAP, SOAP ,
(. 7.1).
, - ASP.NET.

ASP.NET

SOAP

SOAP-

SOAP-

SOAP

7.1. - ASP.NET

, -
125

7. - ASP.NET
SOAP,

SOAP, -
.
- ,
SOAP. SOAP,
(pipeline), SOAP.
.NET Framework 2.0 HTTP
SOAP - ASP.NET,
SOAP , WSE (Web Service
Enhancements).

- ASP.NET,

, Microsoft
Internet Information Services, IIS (. 7.2) .

ASP.NET +WSE

SOAP

SOAP

IIS / http.sys

HTTP

WSE 3.0

TCP/IP

TCP/IP

HTTP, IIS, ASP.NET

TCP, WSE

7.2. -

126

7. - ASP.NET
WSE 3.0 - TCP
IIS. II ASP.NET
IIS.
- ASP.NET , .NET
Framework, ,
-. .NET Framework WSDL-
-,
. .NET Framework
-, - ASP.NET. ,
CLI Mono
- ASP.NET ( 1.1 2.0)
Apache XSP.
-
. ,
-, ,
. , WS-Transaction
WS-BusinessActivity,
, -.
, , , .NET Framework
3.0. - ASP.NET
, , .
- ,
,
. UDDI (Universal Description,
Discovery, and Integration), WS-I
- .
- Microsoft Windows
2003 J2EE.
-,

2005-

127

7. - ASP.NET
, -,

UDDI . ,
- .
7.2.

WSE

- ASP.NET WSE. WSE


3.0 IIS,
,

TCP. WSE

-,
,
SOAP-,
SOAP.
(pipeline), . 7.3.
WSE

WSE

7.3 WSE
128

7. - ASP.NET
WSE (policy)
- .
-.

(assertions

extensions),

.
WSE (
) , (
).
-
( 7.4). ,
( wse3policyCache.config),
(web.config) .
WseConfigEditor3.exe .
WSE

WSE


app.exe.config


web.config


wse3policyCache.config


wse3policyCache.config

7.4 WSE
web.config WSE.

<system.web><webServices><soapServerProtocolFactory> WSE

SOAP.

<microsoft.web.services3><diagnostics>

,
.

129

7. - ASP.NET
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<webServices>
<soapServerProtocolFactory type="Microsoft.Web.Services3.WseProtocolFactory,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
</webServices>
<compilation debug="false">
<assemblies>
<add assembly="Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31BF3856AD364E35" />
</assemblies>
</compilation>
</system.web>
<microsoft.web.services3>
<diagnostics>
<trace enabled="true" input="C:\Inetpub\logs\InputTrace.webinfo"
output="C:\Inetpub\logs\OutputTrace.webinfo" />
</diagnostics>
<policy fileName="wse3policyCache.config" />
</microsoft.web.services3>
</configuration>


.
7.3.

- .NET Framework

, -

. - ASP.NET
. ,
SOAP ASP.NET .
-
ASP.NET IIS ( C:\Inetpub\wwwroot\)
.asmx .
<%@ WebService class="SampleService" language="C#" %>

, URL
SOAP/HTTP - SampleService.
- ,
bin. - .
130

7. - ASP.NET
-

System.Web.Services.WebServiceAttribute,

Description Namespace
, -
WSDL. URI,
-.

URL.

System.Web.Services.WebService.
-

WSE

3.0

Microsoft.Web.Services3.PolictyAttribute, ,

.
, - ,
System.Web.Services.WebMethodAttribute.
Description TransactionOption. -
.
COM+. , -
, .
- .NET Framework 2.0 / WSE 3.0
. - .
<%@ WebService class="BankAccount" language="C#" %>
using
using
using
using

System;
System.Web.Services;
System.EnterpriseServices;
Microsoft.Web.Services3;

[WebService(Namecpace=http://super.bank/webservices)]
[Policy(BankAccountService)]
public class BankAccount : WebService
{
[WebMethod(TransactionOption=TransactionOption.RequiresNew]
public void Transfer(double Amount)
{
// ...
//
ContextUtil.SetComplete();
}
}

131

7. - ASP.NET
- SoapRpcMethodAttribute
SoapDocumentMethodAttribute.
WSDL. , SoapDocumentMethodAttribute
SOAP-Document, ,
SoapRpcMethodAttribute
SOAP-RPC, . ,
SOAP
XmlSerializer,
- ,
XmlSerializer. SoapDocumentMethod SoapRpcMethod
OneWay,
.
-
WSE 3.0
WseWsdl3.exe. .
WseWsdl3.exe http://localhost/service.asmx?wsdl /type:webClient /out:proxy.cs

URL WSDL-

proxy.cs

-,

Microsoft.Web.Services3.WebServicesClientProtocol. -
WSDL ASP.NET -.
c ,
- . ,
WSE
.
[Policy("BankClientPolicy")]
public partial class BankService :
Microsoft.Web.Services3.WebServicesClientProtocol
{
}

, , xsd.exe
XML-, ,
132

7. - ASP.NET
. CLR
XSD- ,

(. 7.5).

ASP.NET

WSDL-

WseWsdl3.exe
wsdl.exe

7.5. -
- .
, Transfer, :

Transfer -;

BeginTransfer EndTransfer
BeginInvoke/EndInvoke;

TransferAsync ( )
InvokeAsync.

BeginInvoke/EndInvoke/InvokeAsync
, .
CancelAsync ( -)
InvokeAsync.

WseWsdl3.exe

.
wsdl.exe .NET SDK, WSE,
.
, .
7.4.

WSE

-
ASP.NET WSE, -
133

7. - ASP.NET
( 10 8 ).
SOAP

Microsoft.Web.Services3.Design.PolicyAssertion.
// TimeAssertion.cs
using System;
using System.IO;
using System.Reflection;
using System.Xml;
using System.Xml.Serialization;
using System.Collections.Generic;
using Microsoft.Web.Services3;
using Microsoft.Web.Services3.Design;
using Microsoft.Web.Services3.Security;
[assembly:AssemblyVersionAttribute("1.0.0.0")]
namespace Seva.WS.Assertions
{
public class TimeAssertion: PolicyAssertion
{
private TimeIntervals intervals;
public TimeAssertion(): base()
{
intervals = null;
}

ReadXml .

.
public override void ReadXml(XmlReader reader,
IDictionary<string, Type> extensions)
{
string fileName = reader.GetAttribute("file");
if (fileName == null)
throw new Exception("Attribute 'file' not found in policy");
// - ,
//
reader.Read();
//
using (StreamReader timeReader = new StreamReader(fileName))
{
XmlSerializer serializer = new
XmlSerializer(typeof(TimeIntervals));
intervals = (TimeIntervals) serializer.Deserialize(
new XmlTextReader(timeReader));
}
}

134

7. - ASP.NET
Create....Filter SOAP,
.
CreateServiceInputFilter ,
.
public override SoapFilter CreateClientInputFilter(
FilterCreationContext context)
{
return null;
}
public override SoapFilter CreateClientOutputFilter(
FilterCreationContext context)
{
return null;
}
public override SoapFilter CreateServiceInputFilter(
FilterCreationContext context)
{
return new CheckTimeFilter(intervals, context);
}
public override SoapFilter CreateServiceOutputFilter(
FilterCreationContext context)
{
return null;
}
}

Microsoft.Web.Services3.SoapFilter
. ,
.
public class CheckTimeFilter : SoapFilter
{
private TimeIntervals intervals;
public CheckTimeFilter(TimeIntervals intervals,
FilterCreationContext context)
{
this.intervals = intervals;
}

ProcessMessage , SOAP.
SoapEnvelope.

135

7. - ASP.NET
public override SoapFilterResult ProcessMessage(SoapEnvelope envelope)
{
if (! intervals.Check(DateTime.Now))
throw new Exception("Service is unavailable now.");
return SoapFilterResult.Continue;
}
}

TimeInterval . TimeSpan,
DateTime,
XML,
,
.
<TimeInterval Inverse="false" From="09:00:00" To="10:30:00" />

XML
, XML-.
[Serializable]
public class TimeInterval
{
[XmlAttribute("From")]
public string FromField
{
set {From = TimeSpan.Parse(value);}
get {return From.ToString();}
}
[XmlAttribute("To")]
public string ToField
{
set {To = TimeSpan.Parse(value);}
get {return To.ToString();}
}
[XmlAttribute("Inverse")]
public bool Inverse;
[XmlIgnore]
public TimeSpan From;
[XmlIgnore]
public TimeSpan To;
public bool Check(DateTime Time)
{
bool result = (From <= Time.TimeOfDay) && (Time.TimeOfDay <= To);
if (Inverse)
result = ! result;
return result;
}
}

136

7. - ASP.NET
TimeIntervals
.
[XmlRoot("TimeIntervals")]
public class TimeIntervals: List<TimeInterval>
{
public TimeIntervals()
{
}
public bool Check(DateTime Time)
{
foreach (TimeInterval interval in this)
if (interval.Check(Time))
return true;
return false;
}
}
}

WSE GAC.
make- GAC
nmake && nmake install.
# : makefile
all: Seva.WS.TimeAssertion.dll
Seva.WS.TimeAssertion.dll: TimeAssertion.cs TimeAssertion.key
csc /t:library /out:Seva.WS.TimeAssertion.dll /keyfile:TimeAssertion.key
/r:Microsoft.Web.Services3.dll TimeAssertion.cs
TimeAssertion.key:
sn -k TimeAssertion.key
install:
gacutil -nologo -i Seva.WS.TimeAssertion.dll`

.
1. -,
.
<?xml version="1.0" encoding="utf-8"?>
<TimeIntervals>
<TimeInterval Inverse="true" From="09:00:00" To="20:00:00" />
<TimeInterval Inverse="false" From="13:00:00" To="13:30:00" />
</TimeIntervals>

2. wse3policyCache.config (
,
WSE).
137

7. - ASP.NET
<policies xmlns="http://schemas.microsoft.com/wse/2005/06/policy">
<extensions>
<extension name="timeIntervals" type="Seva.WS.Assertions.TimeAssertion,
Seva.WS.TimeAssertion, Version=1.0.0.0, Culture=neutral, PublicKeyToken=..." />
</extensions>
<policy name="MyServicePolicy">
<timeIntervals file="C:\Inetpub\wwwroot\timeschema.config" />
</policy>
</policy>
</policies>

MyServicePolicy ,
Policy -.
7.5.

WSE ,
- , :

Kerberos ( Active Directory);

X.509;

,
( ) (

TCP).

WseConfigEditor3.exe WSE.
WSE
Windows, .
-
. WSE

(Microsoft.Web.Services3.Design.TokenProvider).
SOAP,
WSE. , ,
UsernameOverTransportAssertion

UsernameForCertificateAssertion,


.
138

7. - ASP.NET

web.config

<microsoft.web.services3><security><securityTokenManager>.

, localName,
.
<microsoft.web.services3>
<security>
<securityTokenManager>
<add localName="UsernameToken" type="Seva.WS.Users.UsersListManager,
Seva.WS.UsersManager, Version=1.0.0.0, Culture=neutral, PublicKeyToken=..."
namespace="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecuritysecext-1.0.xsd" >
<users file="C:\Inetpub\users.config"/>
</add>
</securityTokenManager>
</security>
<policy fileName="wse3policyCache.config" />
</microsoft.web.services3>


SOAP ( <wsse:Security>)
, VerifyToken.
UsernameTokenManager, SOAP
<wsse:UsernameToken>.

UsernameTokenManager, ,
SecurityTokenManager.
, UsernameTokenManager
, AuthenticateToken
, SOAP.
, , .
(),
. AuthenticateToken .
, SOAP
( , ,
X.509) , (digest).
, (nonce),
:
Password_Digest = Base64(SHA1( nonce + created + password)),
139

7. - ASP.NET
SHA1 .

-. ,

, .

SSL.

,
( VerifyPlainTextPassword). ,
, .
,
.
SOAP <wsse:UsernameToken>,
UsernameToken PasswordOption.SendHashed.
- .
// UsersManager.cs
using System;
using System.IO;
using System.Reflection;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Security;
using
using
using
using

Microsoft.Web.Services3;
Microsoft.Web.Services3.Design;
Microsoft.Web.Services3.Security;
Microsoft.Web.Services3.Security.Tokens;

WSE
GAC, .

140

7. - ASP.NET
[assembly:AssemblyVersionAttribute("1.0.0.0")]
namespace Seva.WS.Users
{
public class UsersListManager: UsernameTokenManager
{
private UsersList users;
public UsersListManager()
{
users = new UsersList();
}

UsersListManager

AuthenticateToken.
public UsersListManager(XmlNodeList configData): base(configData)
{
string fileName = configData[0].Attributes["file"].Value;
users = UsersList.Load(fileName);
}
protected override string AuthenticateToken(UsernameToken token)
{
if (!users.Users.ContainsKey(token.Username))
return null;
return users.Users[token.Username];
}

VerifyPlainTextPassword .
protected override void VerifyPlainTextPassword(UsernameToken token,
string authenticatedPassword)
{
if (token==null)
throw new ArgumentNullException("token is null");
String hashed = Utils.HashedPassword(token.Password);

if (authenticatedPassword==null || authenticatedPassword=="" ||
hashed!=authenticatedPassword)
throw new Exception("Passwords does not match ");

UsersList.
XmlSerialiser,
IXmlSerializable.

141

7. - ASP.NET

[XmlRoot("users")]
public class UsersList: IXmlSerializable
{
private Dictionary<string, string> usersField;
public Dictionary<string, string> Users
{
get {return usersField;}
}
public UsersList()
{
usersField = new Dictionary<string, string>();
}
public void ReadXml(XmlReader reader)
{
reader.Read();
while (reader.NodeType != XmlNodeType.EndElement)
{
Users.Add(reader.GetAttribute("username"),
reader.GetAttribute("password"));
reader.Read();
}
}
public void WriteXml(XmlWriter writer)
{
foreach (string user in Users.Keys)
{
writer.WriteStartElement("user");
writer.WriteAttributeString("username", user);
writer.WriteAttributeString("password", this.Users[user]);
writer.WriteEndElement();
}
}
public XmlSchema GetSchema()
{
return null;
}

NewUser .
public void NewUser(string userName, string password, bool hashed)
{
if (Users.ContainsKey(userName))
{
throw new ApplicationException("Duplicate username.");
}
if (hashed)
{
password = Utils.HashedPassword(password);
}
Users.Add(userName, password);
}

142

7. - ASP.NET
Load Save ( )
.
public static UsersList Load(string fileName)
{
XmlSerializer serializer = new XmlSerializer(typeof(UsersList));
using (StreamReader reader = new StreamReader(fileName))
{
return (UsersList) serializer.Deserialize(reader);
};
}
public void Save(string fileName)
{
XmlSerializer serializer = new XmlSerializer(typeof(UsersList));
using (StreamWriter writer = new StreamWriter(fileName))
{
serializer.Serialize(writer, this);
};
}
}

Utils
.
static class Utils
{
public static string HashedPassword(string password)
{
SHA1CryptoServiceProvider crypto = new SHA1CryptoServiceProvider();
byte[] inputBuffer = Encoding.Unicode.GetBytes(password);
return Convert.ToBase64String(crypto.ComputeHash(inputBuffer));
}
}

make- c
GAC nmake && nmake install.
all: Seva.WS.UsersManager.dll
Seva.WS.UsersManager.dll: UsersManager.cs UsersManager.key
csc /t:library /out:Seva.WS.UsersManager.dll /keyfile:TimeAssertion.key
/r:Microsoft.Web.Services3.dll UsersManager.cs
UsersManager.key:
sn -k UsersManager.key
install:
gacutil -nologo -i Seva.WS.UsersManager.dll

(web.config)
<microsoft.web.services3> <security>.
143

7. - ASP.NET
<?xml version="1.0" encoding="utf-8"?>
<configuration>
...
<microsoft.web.services3>
<security>
<securityTokenManager>
<add type="Seva.WS.Users.UsersListManager, Seva.WS.UsersManager,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=..."
namespace=
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
localName="UsernameToken">
<users file="C:\Inetpub\users.config"/>
</add>
</securityTokenManager>
</security>
<policy fileName="wse3policyCache.config" />
</microsoft.web.services3>
</configuration>

,
.

<policy><authorization> -

, <allow> <deny>.

UsernameClientAssertion.

-,
X.509. X.509

.
[XmlRoot("user")]
public struct UserCredential
{
[XmlAttribute("username")]
public string Username;
[XmlAttribute("password")]
public string Password;
}
public class UsernameClientAssertion: SecurityPolicyAssertion
{
private UserCredential credential;
public UsernameClientAssertion()
{
}

ReadXml ,
.
144

7. - ASP.NET
.
(,
) -
.
public override void ReadXml(XmlReader reader,
IDictionary<string, Type> extensions)
{
string fileName = reader.GetAttribute("file");
if (fileName == null)
throw new Exception("Attribute 'file' not found in policy");
// -
reader.Read();
using (StreamReader stream = new StreamReader(fileName))
{
XmlSerializer serializer = new
XmlSerializer(typeof(UserCredential));
using (XmlTextReader xmlReader = new XmlTextReader(stream))
{
credential = (UserCredential) serializer.Deserialize(xmlReader);
}
}
}

CreateClientOutputFilter SOAP,
.
public override SoapFilter CreateClientOutputFilter(
FilterCreationContext context)
{
return new UsernameClientFilter(this, credential, context);
}
public override SoapFilter CreateClientInputFilter(
FilterCreationContext context)
{
return null;
}
public override SoapFilter CreateServiceInputFilter(
FilterCreationContext context)
{
return null;
}
public override SoapFilter CreateServiceOutputFilter(
FilterCreationContext context)
{
return null;
}
}

145

7. - ASP.NET
SendSecurityFilter
SecureMessage.
class UsernameClientFilter : SendSecurityFilter
{
private UserCredential credential;
public UsernameClientFilter(UsernameClientAssertion assertion,
UserCredential credential, FilterCreationContext filterContext)
: base(assertion.ServiceActor, true, assertion.ClientActor)
{
this.credential = credential;
}
public override void SecureMessage(SoapEnvelope envelope,
Security security)
{
UsernameToken userToken = new UsernameToken(credential.Username,
credential.Password, PasswordOption.SendHashed);
security.Tokens.Add(userToken);
}
}
}

.
// AddUser.cs
using System;
using System.IO;
using Seva.WS.Users;
class MainApp
{
public static int Main(string[] Args)
{
if (Args.Length < 3)
{
Console.WriteLine(
"usage: adduser <users' file> <username> <password> [--hashed]");
return 1;
}
UsersList users = new UsersList();
string fileName = Args[0];
if (File.Exists(fileName))
{
users = UsersList.Load(fileName);
}
bool hashed = false;
if (Args.Length==4)
{
hashed = Args[3]=="--hashed";
}

146

7. - ASP.NET
users.NewUser(Args[1], Args[2], hashed);
users.Save(fileName);
return 0;
}
}

WSE
UsernameOverTransportAssertion

,
wse3policyCache.config .
<policies xmlns="http://schemas.microsoft.com/wse/2005/06/policy">
<extensions>
<extension name="usernameOverTransportSecurity"
type="Microsoft.Web.Services3.Design.UsernameOverTransportAssertion,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
<extension name="requireActionHeader"
type="Microsoft.Web.Services3.Design.RequireActionHeaderAssertion,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
</extensions>
<policy name="ServicePolicy">
<usernameOverTransportSecurity />
<requireActionHeader />
</policy>
</policies>

UsernameClientAssertion
.
<policies xmlns="http://schemas.microsoft.com/wse/2005/06/policy">
<extensions>
<extension name="simpleUserName" type="Seva.WS.Users.UsernameClientAssertion,
Seva.WS.UsersManager, Version=1.0.0.0, Culture=neutral, PublicKeyToken=..."/>
</extensions>
<policy name="ClientPolicy">
<simpleUserName file="user.xml"/>
</policy>
</policies>

user.xml -.
<user username="user2" password="222" />

, , X.509
UsernameForCertificateAssertion
UsernameClientAssertion ,
.
UsernameForCertificateAssertion
147

7. - ASP.NET
, .

WseConfigEditor3.exe.
7.6.

-
. .NET
WSE
. -
.
1. . -
.
TCP/IP, NAT ,
HTTP. -
.
2. , . -
,
IIS ,
-.
.
3. .

WSE

WS-Security

1.1

,
.
4. .
-
- . - .NET
, , .NET Framework 3.0 WCF.

148

7. - ASP.NET
5. ( ). SOAP
,
-.
- , ,
.
WSE
.
WS-* -
. - ASP.NET
,
TCP/IP.

149

8. .NET Remoting

8. .NET Remoting
.NET Remoting,
.
.NET Remoting .

8.1.

.NET Remoting

, ,
.NET Remoting .NET. Remoting
,

. Remoting
.
Remoting
- SOAP,

(. 8.1).

SOAP-

.NET
Remoting

.NET
Remoting

HTTP / SOAP

TCP /

HTTP / SOAP

.NET Remoting

8.1. Remoting
150

8. .NET Remoting
, .NET
Remoting .NET Framework
COM+ .NET Enterprise Services.
Remoting, CLR .
1. , .
,
. ,
. ,
,
.
2. , .
System.MarshalByRefObject.

, ,
.
Remoting. Remoting
: ,
, .
3. ,
, .
. , ,

Remoting

.
, Remoting
CLR. MSMQ COM+,
Remoting - Microsoft
Windows. Remoting
CLI,
System.EnterpriseServices System.Messaging. ,
Remoting CLI
151

8. .NET Remoting
Microsoft (.NET Framework, .NET Compact Framework),
CLI ( Mono Project DotGNU
Portable.NET).
Remoting CLI
. Remoting
Enterprise Services. Remoting
COM+,
. Remoting -
,
- Remoting, Internet
Information Services (IIS).
8.2.

.NET Remoting

Remoting ,

Remoting . ,
, Remoting
(, MSMQ)
(, CLR COM+).


. , Remoting
, ,
, ,


, , .

152

8. .NET Remoting
.Net Remoting




.Net Remoting

.Net Remoting


.Net Remoting

8.2. .NET Remoting


Remoting (. 8.2)
, System.Runtime.Remoting
.
1.

TransparentProxy RealProxy.
153

8. .NET Remoting
. ,
,
( IMessage).

- ,
Remoting .
2. (channel) Remoting.
(sinks) . ,
,
-, ,
. , ,
, .

. ,
.
( ) IMessageSink.

(message sinks).

,
(channel sinks). IlientChannelSink
IServerChannelSink .
, ,
.
3.

ChannelServices.DispatchMessage) .
4. , Remoting,
. IChannel, IChannelSender,
IChannelReceiver
/ , . Remoting
. HttpChannel TcpChannel
HTTP TCP , .NET Framework 2.0
154

8. .NET Remoting
IpcChannel
(IPC: inter-process communication) .

: BinaryFormatter SoapFormatter.

System.Runtime.Remoting.ObjRef.

.
System.MarshalByRefObject Remoting
ObjRef,
Remoting
(. 8.3).
.NET
Remoting

Remoting


ObjRef

Remoting

.NET Remoting

8.3. Remoting

Remoting

,
MarshalByRefObject.
155

8. .NET Remoting
OneWayAttribute2. -
, .
. Remoting
,

, . Remoting
.

.
, ,
. Remoting

(lease),



. ,
,
.
,

(
set get ). , ,
, .
8.3.

.NET Remoting

Remoting
XML-. Remoting :

(, TCP);

BeginInvoke ,

156

8. .NET Remoting

Remoting
, .

,

.
,

Remoting

Remoting
(. 8.4).

.Net Remoting
.NET Remoting
.NET Remoting
RemoteWorker worker =
new RemoteWorker();
results = worker.DoWork();

RemoteWorker

RemoteReport report =
new RemoteReport();
report.ReportResults(results);

RemoteWorker

.NET Remoting

.Net Remoting

.Net Remoting

8.4. Remoting
, ,
, Remoting.
IIS, ,
.
.NET Remoting.
157

8. .NET Remoting
// server.cs
using System;
using System.Runtime.Remoting;
using System.Configuration;
public class Server
{
public static void Main(string[] args)
{
string config = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
Console.WriteLine(config);
RemotingConfiguration.Configure(s);
// .NET Framework 2.0
// RemotingConfiguration.Configure(s, false);
Console.WriteLine(" ENTER .");
Console.ReadLine();
}
}

,
Remoting .

Remoting, .
<configuration>
<system.runtime.remoting>
<application>
<service>
<wellknown mode="SingleCall"
type="RemoteTest.TestService, RemoteTestService"
objectUri="endpoint"/>
</service>
<channels>
<channel ref="tcp" port="2080" />
</channels>
</application>
</system.runtime.remoting>
</configuration>

<application> <service> .
, (
, ), URI,
. , ,
<wellknown mode="SingleCall" type=...


<wellknown mode="Singletone" type=...

. , ,
.
<activated type=...

158

8. .NET Remoting

<application><channels>

. ,

,
.
.
<configuration>
<system.runtime.remoting>
<application>
<client>
<wellknown mode="SingleCall"
type="RemoteTest.TestService, RemoteTestService"
objectUri="tcp://127.0.0.1:2080/endpoint" />
</client >
</application>
</system.runtime.remoting>
</configuration>

<application><client> .
, <service>,
<client>. Remoting
.
, , Remoting.

<client> ,
.
using System;
using System.Runtime.Remoting;
using RemotingTest;
public class Client
{
public static void Main(string[] args)
{
string config = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
Console.WriteLine(config);
RemotingConfiguration.Configure(config);
//
// ,
TestService service = new RemotingTest.TestService();

159

8. .NET Remoting

//
Console.WriteLine(service.Sum(2, 2));

.
,
.
// TestService.cs
using System;
namespace RemotingTest
{
public class TestService : MarshalByRefObject
{
public TestService()
{
Console.WriteLine("[ctor]");
}
~TestService()
{
Console.WriteLine("[dtor]");
}
public int Sum(int a, int b)
{
return a + b;
}
}
}

make- .
, CLI
System.Runtime.Remoting.dll. .NET Framework 2.0
C# (csc.rsp).
makefile : Server.exe Client.exe
Server.exe : Server.cs
csc Server.cs
Client.exe : Client.cs RemoteTestService.dll
csc /r:RemoteTestService.dll Client.cs
RemoteTestService.dll: TestService.cs
csc /out:RemoteTestService.dll /t:library TestService.cs

8.4.

- .NET Remoting

Remoting
. ,
160

8. .NET Remoting
, .

System.Activator, - Remoting
SOAP,
- WSDL. -
, , ,
,
.
SoapFormatter, HttpChannel
Remoting -
SOAP, WSDL SOAP-RPC ( SOAP-Document,
ASP.NET). ,
,

System.Runtime.Remoting.MetadataServices.MetaData,

-. soapsuds.exe.
,
System.Runtime.Remoting.Services.RemotingClientProxy,
Remotig.
soapsuds.exe -url:http://localhost:2080/endpoint?wsdl -gc

, -
( ,
soapsuds.exe). soapsuds.exe
, Remoting.
RemotingConfiguration.Configure,
, ,
. Remoting
-, wsdl.exe
-.
Remoting
IIS, HTTP.
161

8. .NET Remoting
web.config ,
bin .
Remoting ,

IIS.
SSL. SSL,
, https://.
IIS
.
RemoteObject object = new RemoteObject();
//
IDictionary properties = ChannelServices.GetChannelSinkProperties(object);
properties["username"] = username;
properties["password"] = password;
//
object.Do();

IIS
PrincipalPermissionAttribute, ,
,
.
IPrincipal principal = System.Threading.Thread.CurrentPrincipal;
if (!principal.IsInRole(Environment.MachineName + @"\SomeGroup"))
{
throw new UnauthorizedAccessException(" .");
}

Active
Directory IIS ,
.
<channel ref="http" useDefaultCredentials="true" />

, Active Directory IIS


Remoting Windows
( Kerberos), .
162

8. .NET Remoting
Active Directory Windows
.
8.5.

Remoting

, Remoting ,
, (chain).
, ,
. NextSink (
IMessageSink)

NextChannelSink

IClientChannelSink

IServerChannelSink).
.Net Remoting

8.5.
(sink providers).

IClientChannelSinkProvider

IServerChannelSinkProvider,
163

8. .NET Remoting
CreateSink (. 8.5). , (
IMessageSink)

CreateMessageSink.
, ,
.
ChannelServices.CreateServerChannelSinkChain,

DispatchChannelSinkProvider.
,
, .
, Next.

. , TcpClientChannel (
TcpChannel) BinaryClientFormatterSinkProvider
TcpClientTransportSinkProvider.
.

<channel><serverProviders><formatter>

<channel><clientProviders><formatter> .
binary soap.
<configuration>
<system.runtime.remoting>
<application>
<service>
<wellknown mode="SingleCall"
type="RemotingTest.TestService, RemoteTestService"
objectUri="endpoint"/>
</service>
<channels>
<channel ref="http" port="2080">
<serverProviders>
<formatter ref="binary"/>
</serverProviders>
</channel>
</channels>
</application>
</system.runtime.remoting>
</configuration>

164

8. .NET Remoting

.
- .
,

Remoting IIS, VPN
(, OpenVPN).

.NET Remoting.

, ,
.
.

<channel><clientProviders><provider>.
,
.
FCL III.
// SevaRemotingEncrypted.cs
using System;
using System.IO;
using System.Collections;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Messaging;
using Seva.Security.Encryption;
namespace Seva.Remoting.Encryption
{
class EncryptedClientChannelSinkProvider: IClientChannelSinkProvider
{
private IClientChannelSinkProvider next;
public IClientChannelSinkProvider Next
{
get { return next; }
set { next = value; }
}
private SymmetricEncryptor encryptor;

165

8. .NET Remoting

, .
,
.
public EncryptedClientChannelSinkProvider(IDictionary properties,
ICollection providerData)
{
string keyFile = (string) properties["key"];
Console.WriteLine("Client key: [{0}]", keyFile);
encryptor = new SymmetricEncryptor(keyFile);
}

CreateSink .
,
, . ,
, Next
.
public IClientChannelSink CreateSink(IChannelSender channel,
string url, object remoteChannelData)
{
IClientChannelSink next = Next.CreateSink(channel,
url, remoteChannelData);
return new EncryptedClientChannelSink(encryptor, next);
}
}

.
class EncryptedServerChannelSinkProvider : IServerChannelSinkProvider
{
private IServerChannelSinkProvider next;
private SymmetricEncryptor encryptor;
public IServerChannelSinkProvider Next
{
get { return next; }
set { next = value; }
}
public EncryptedServerChannelSinkProvider(IDictionary properties,
ICollection providerData)
{
string keyFile = (string) properties["key"];
Console.WriteLine("Server key: [{0}]", keyFile);
encryptor = new SymmetricEncryptor(keyFile);
}

166

8. .NET Remoting
//
public IServerChannelSink CreateSink(IChannelReceiver channel)
{
IServerChannelSink nextSink = Next.CreateSink(channel);
return new EncryptedServerChannelSink(channel, encryptor, nextSink);
}
//
public void GetChannelData(IChannelDataStore channelData)
{
}
}


.
class EncryptedServerChannelSink : IServerChannelSink
{
public IDictionary Properties
{
get { return null; }
}
private IServerChannelSink nextSink;
public IServerChannelSink NextChannelSink
{
get { return nextSink; }
}
private SymmetricEncryptor encryptor;
public EncryptedServerChannelSink(IChannelReceiver channel,
SymmetricEncryptor channelEncryptor, IServerChannelSink next)
{
encryptor = channelEncryptor;
nextSink = next;
}


ProcessMessage.
, .

.
//
public ServerProcessing ProcessMessage(IServerChannelSinkStack sinkStack,
IMessage requestMsg, ITransportHeaders requestHeaders,
Stream requestStream, out IMessage responseMsg,
out ITransportHeaders responseHeaders, out Stream responseStream)
{
Stream plainStream = null;
MemoryStream decodedStream = new MemoryStream();
requestStream = Utils.ReadAllStream(requestStream);

167

8. .NET Remoting
//
encryptor.Decrypt(requestStream, decodedStream);
decodedStream.Position = 0;
ServerProcessing result = nextSink.ProcessMessage(sinkStack,
requestMsg, requestHeaders, decodedStream, out responseMsg,
out responseHeaders, out plainStream);
//
responseStream = new MemoryStream();
encryptor.Encrypt(plainStream, responseStream);
responseStream.Position = 0;
//
return result;
}
public void AsyncProcessResponse(IServerResponseChannelSinkStack sinkStack,
Object state, IMessage msg, ITransportHeaders headers, Stream stream)
{
throw new NotSupportedException();
}
public Stream GetResponseStream(IServerResponseChannelSinkStack sinkStack,
Object state, IMessage msg, ITransportHeaders headers)
{
return nextSink.GetResponseStream(sinkStack, state, msg, headers);
}
} // EncryptedServerChannelSink


.
class EncryptedClientChannelSink: IClientChannelSink
{
public IDictionary Properties
{
get { return null; }
}
private IClientChannelSink nextSink;
public IClientChannelSink NextChannelSink
{
get { return nextSink; }
}
private SymmetricEncryptor encryptor;
public EncryptedClientChannelSink(SymmetricEncryptor channelEncryptor,
IClientChannelSink next)
{
encryptor = channelEncryptor;
nextSink = next;
}

168

8. .NET Remoting
public void ProcessMessage(IMessage message,
ITransportHeaders requestHeaders, Stream requestStream,
out ITransportHeaders responseHeaders, out Stream responseStream)
{
MemoryStream encryptedStream = new MemoryStream();
Stream serverStream = null;
//
encryptor.Encrypt(requestStream, encryptedStream);
encryptedStream.Position = 0;
nextSink.ProcessMessage(message, requestHeaders, encryptedStream,
out responseHeaders, out serverStream);
serverStream = Utils.ReadAllStream(serverStream);
//
responseStream = new MemoryStream();
encryptor.Decrypt(serverStream, responseStream);
responseStream.Position = 0;
}
public Stream GetRequestStream(IMessage msg, ITransportHeaders headers)
{
return null;
}
public void AsyncProcessRequest(IClientChannelSinkStack sinkStack,
IMessage message, ITransportHeaders headers, Stream stream)
{
throw new NotSupportedException();
}
public void AsyncProcessResponse(
IClientResponseChannelSinkStack sinkStack, object state,
ITransportHeaders headers, Stream stream)
{
throw new NotSupportedException();
}
} // EncryptedClientChannelSink

Utils ,
Length.
public static class Utils
{
public static MemoryStream ReadAllStream(Stream input)
{
byte[] buffer = new byte [1024];
MemoryStream output = new MemoryStream();
while (true)
{
int read = input.Read(buffer, 0, buffer.Length);
output.Write(buffer, 0, read);
if (read < buffer.Length) break;
}
output.Position = 0;
return output;
}
}
}
// SevaRemotingEncrypted.cs

169

8. .NET Remoting
make-.
makefile : Client.exe SevaRemotingEncrypted.dll
common = Seva*.cs
Client.exe : Client.cs RemoteService.dll
csc /r:RemoteService.dll Client.cs
RemoteService.dll : RemoteService.cs
csc /t:library RemoteService.cs
SevaRemotingEncrypted.dll: $(common)
csc /out:SevaRemotingEncrypted.dll /t:library $(common)

,
.
.
<configuration>
<system.runtime.remoting>
<application>
<client>
<wellknown
type="RemoteService.RemoteServiceTest, RemoteService"
url="tcp://localhost:10020/endpoint"
/>
</client>
<channels>
<channel ref ="tcp">
<clientProviders>
<formatter ref="binary"/>
<provider type="Seva.Remoting.Encryption.
EncryptedClientChannelSinkProvider, SevaRemotingEncrypted"
key="secret.key"
/>
</clientProviders>
</channel>
</channels>
</application>
</system.runtime.remoting>
</configuration>

, .NET Remoting
Remoting, -
.
.
8.6.

Remoting
.
170

8. .NET Remoting
Remoting ,
TCP/IP.
Remoting
MSMQ.
TcpChannel HttpChannel,
.
.
8.6. . ,
MSMQ,
, MSMQ.

IMessage

IMessage

MSMQ
MSMQ

MSMQ
IMessage

8.6. Remoting, MSMQ

System.Runtime.Remoting.Messaging.OneWayAttribute,
.

171

8. .NET Remoting
: c
MsmqChannelSender, IChannelSender,
MsmqChannelReceiver, IChannelReceiver.
MSMQ MsmqClient MsmqServer,
MSMQ.
// SevaRemotingMsmq.cs
using System;
using System.IO;
using System.Collections;
using
using
using
using
using

System.Runtime.Remoting;
System.Runtime.Remoting.Channels;
System.Runtime.Remoting.Messaging;
System.Runtime.Serialization.Formatters.Binary;
System.Messaging;

using System.Text.RegularExpressions;
// MSMQ
// c
using Seva.Msmq;
//
// Remoting / MSMQ
namespace Seva.Remoting.MsmqChannel
{
//
public class MessageProperties
{
public const string Uri
= "__Uri";
public const string ObjectUri
= "__ObjectUri";
}

MsmqBase .
Parse, URL
. URL

msmq://.\Private$\remoting_queue\endpoint

.\Private$\remoting_queue ( , ),
endpoint .
// MsmqSender MsmqReceiver
public class MsmqBase: MarshalByRefObject, IChannel
{
// IChannel
public int ChannelPriority { get { return 1;} }
public string ChannelName { get{ return "msmq";} }

172

8. .NET Remoting
// URL
public string Parse(string url, out string objectUri)
{
return Utils.ParseUrl(url, out objectUri);
}
}

MsmqChannelSender clientSinkProvider
, ,
.
, MSMQ.
Remoting
, ,
.
//
public class MsmqChannelSender: MsmqBase, IChannelSender
{
public MsmqChannelSender(IDictionary properties,
IClientChannelSinkProvider clientSinkProvider)
{
// MSMQ,
//
if (clientSinkProvider!=null)
{
throw new NotSupportedException(
" .");
}
}

CreateMessageSink, IChannelSender,
.
public IMessageSink CreateMessageSink(string url,
object channelData, out string objectUri)
{
// URL
string remoteobjectUrl = Utils.ParseUrl(url, ChannelName,
out objectUri);
if (remoteobjectUrl == null)
return null;
//
return new MsmqClientChannelSink(remoteobjectUrl);
}
} // Seva.Remoting.MsmqChannel.Msmq.MsmqSender

MsmqClientChannelSink

MSMQ.
173

8. .NET Remoting
//
public class MsmqClientChannelSink: IMessageSink
{
// MSMQ, IMessage
// ,
// void
private MsmqClient<IMessage, IMessage> msmqClient;
// MSMQ (endpoint)
private string queuePath = null;
private string objectUri = null;

MSMQ
.
public MsmqClientChannelSink(string remoteObjectUri)
{
// URL
queuePath = Utils.ParseUrl(remoteObjectUri, out objectUri);
// MSMQ,
//
msmqClient = new MsmqClient<IMessage, IMessage>(queuePath, null,
QueueFormatter.Binary);
}
public IMessage SyncProcessMessage(IMessage msg)
{
throw new NotSupportedException(
" OneWayAttribute.");
}

AsyncProcessMessage .
Remoting MSMQ.
public IMessageCtrl AsyncProcessMessage(IMessage message,
IMessageSink replySink)
{
// c
message.Properties[MessageProperties.ObjectUri] = objectUri;
// MSMQ
msmqClient.Send(message);
return null;
}

// -
public IMessageSink NextSink
{
get { return null; }
}
// Seva.Remoting.MsmqChannel.MsmqClientChannelSink

MsmqChannelReceiver.

174

8. .NET Remoting
public class MsmqChannelReceiver: MsmqBase, IChannelReceiver
{
// - MSMQ Remoting
private MsmqServer<IMessage, IMessage> msmqServer;
//
private IServerChannelSink

sink;

//
private ServerChannelSinkStack stack;
//
public object ChannelData
{
get { return null; }
}

MsmqServer,
.
ProcessMessage .
, .
public MsmqChannelReceiver(IDictionary properties,
IServerChannelSinkProvider serverSinkProvider)
{
// MSMQ
msmqServer = new MsmqServer<IMessage, IMessage>(
properties["queue"].ToString(), QueueFormatter.Binary);
msmqServer.ProcessMessage += OnReceive;
if (serverSinkProvider!=null)
{
throw new NotSupportedException(
" .");
}

MsmqReceiver, MsmqServer,
.
sink = ChannelServices.CreateServerChannelSinkChain(null, this);
//
stack = new ServerChannelSinkStack();
stack.Push(sink, null);
//
StartListening(null);
}
// IChannelReceiver, URL URI
public virtual string[] GetUrlsForUri(string objectURI)
{
return new string[] {objectURI};
}

175

8. .NET Remoting
// MSMQ
private IMessage OnReceive(Object sender, IMessage request,
MessageQueue queueResponse)
{
return ProcessMessage(request);
}
// ,
public void StartListening(Object data)
{
msmqServer.BeginReceive();
}
public void StopListening(Object data)
{
msmqServer.EndReceive();
}

ProcessMessage .NET Remoting.


, ,
Remoting.
private IMessage ProcessMessage(IMessage request)
{
IMessage response = null;
// URI ,
object uri = request.Properties[MessageProperties.ObjectUri];
if (uri == null) return null;
string url = uri.ToString();
// __URI
request.Properties[MessageProperties.Uri] = uri;
//
Stream responseStream = null;
ITransportHeaders responseHeaders = null;
sink.ProcessMessage(stack, request, null, null,
out response, out responseHeaders, out responseStream);
return response;
}
} // Seva.Remoting.MsmqChannel.MsmqReceiver

Utils URL.
public static class Utils
{
// URL
public static string ParseUrl(string url, string channelName,
out string objectUri)
{
objectUri = null;
Regex re = new Regex(@"^" + channelName + @"\:\/\/(.+)$");
Match m = re.Match(url);
if (!m.Success) return null;

176

8. .NET Remoting

string sinkUri = m.Groups[1].Value;


Utils.ParseUrl(url, out objectUri);
return sinkUri;
}
// URL MSMQ
public static string ParseUrl(string url, out string objectUri)
{
string queuePath = null;
objectUri = null;
Regex r = new Regex(@"^(.*)(\\|\/)(.+)$");
Match m = r.Match(url);
if (m.Success)
{
objectUri = m.Groups[3].Value;
queuePath = m.Groups[1].Value;
}
else
{
throw new Exception(" " + url);
}
return queuePath;
}
} // Seva.Remoting.MsmqChannel.Utils
} // Seva.Remoting.MsmqChannel
// SevaRemotingMsmq.cs

make-
.
makefile : SevaRemotingMsmq.dll
common = SevaRemotingMsmq.cs SevaMsmq.cs
SevaRemotingMsmq.dll: $(common)
csc /out:SevaRemotingMsmq.dll /t:library $(common)

,
, <channel>.
<configuration>
<system.runtime.remoting>
<application>
<client>
<wellknown
type="RemoteService.RemoteServiceOneWay, RemoteService"
url="msmq://.\Private$\remoting_queue\service" />
</client>
<channels>
<channel
type="Seva.Remoting.MsmqChannel.MsmqChannelSender, SevaRemotingMsmq"/>
</channels>
</application>
</system.runtime.remoting>
</configuration>

177

8. .NET Remoting
.
<configuration>
<system.runtime.remoting>
<application name="JobServer">
<service>
<wellknown mode="SingleCall"
type="RemoteService.RemoteServiceOneWay, RemoteService"
objectUri="service" />
</service>
<channels>
<channel
type="Seva.Remoting.MsmqChannel.MsmqChannelReceiver, SevaRemotingMsmq"
queue = ".\Private$\remoting_queue"/>
</channels>
</application>
</system.runtime.remoting>
</configuration>

, .NET Remoting
.

.NET Remoting.
8.7.

.NET Remoting

Remoting
.

, IpChannel.
,


IIS.
.NET Remoting
.
Remoting - ( Remoting-Soap)
( Remoting-Binary).
1. . Remoting-Binary
, CLI,
178

8. .NET Remoting
, .
Remoting-Soap ,
SOAP WSDL.
2. . , .NET Remoting,
, .


.
3. . Remoting
.
4. . Remoting
,
.
5. . Remoting-Soap IIS.
IIS Remoting -
,
VPN. ,

Remoting

).

, MSMQ.
6.

Remoting-Binary
.
Remoting ,
. ,
, ,
.
, , .NET Remoting
. , IIS
179

8. .NET Remoting
Remoting -,
- .NET Remoting WSE.
.NET Remoting IIS
- HTTP , ,
IpcChannel. ,
, IIS ,
.NET Remoting. Remoting
LAN TCP ,
.
.NET Remoting
CLI.

180

9. .NET Framework

9.
.NET Framework

,
, .NET Framework.

9.1.

,
(. 9.1).
,
:

(, Remoting COM+ MSMQ);

OSI (, HTTP HTTPS);

OSI (, TCP).

, ,
.

9.1.
181

9. .NET Framework
,
:

();

(
);


().

,
.
- .
- ASP.NET.
:

( WSE);

HTTPS;

IP (IPSec), -
TCP, HTTP.

.NET

Remoting.

, HTTP
HTTPS IIS, MSMQ , IPSec.
Remoting ,
.

.
1. . ,
, .
2. .
-
.

182

9. .NET Framework
3. .
(, -)
.
4.

,
.
.
1. .

.
.
2. .
, .
.
,
.
, ,
.
,
.
9.2.

(public key infrastructure, PKI).

X.509.
PKI

,
.
183

9. .NET Framework
,
(. 9.2).

9.2.
X.509,
, (,
) .
(certificate authority, CA).
,
- MD5, CA.
(. 9.3).
, :

,
.
,
. .

184

9. .NET Framework
(CA)

9.3.
,
PKI (,
Windows Certificate Services).
,

.
.
,
.
:

, ;


, .
185

9. .NET Framework

.
,
, .NET
Framework:

SSL;

IPsec;

HTTPS;

- WS-Security;

MSMQ.

,
,
.
Kerberos
Kerberos
.
Microsoft Windows 2000 .
Kerberos ,
(key distribution center, KDC).
Active Directory
(ticket-granting ticket, TGT),
Kerberos .
KDC,
(service ticket),
, ,
, .
.
,
(authenticator),
186

9. .NET Framework
. .

, .
.
Kerberos Microsoft Windows :

Windows (Windows integrated security, WIS);

IPSec/IKE;

- WS-Security.

Kerberos Microsoft Windows Active


Directory. WIS MSMQ, IIS COM+.
9.3.

.NET Framework

MSMQ LAN;

MSMQ / HTTP: MSMQ 3.0 HTTP / IIS;

Enterprise Services / COM+;

WS: - WSE 3.0;

Remoting IIS, ;

Remoting IIS.

9.1

. VPN
SSL IPSec.
,
Remoting,
.

187

9. .NET Framework
9.1. .NET Framework

MSMQ
MSMQ / HTTP
ES / COM+
WS
Remoting
Remoting / IIS

VPN, WIS

X.509

HTTPS, VPN, WIS

WIS, VPN

(WIS)

HTTPS, VPN, WIS

WS-Security (X.509, Kerberos)

VPN

HTTPS, VPN, WIS

VPN
LAN
Remoting
Active Directory
LAN/VPN
MSMQ

COM+


MSMQ/HTTP

WS

Remoting / IIS

9.4.

. 9.4
.
, ,
,
. ,
188

9. .NET Framework
- ,
, .
9.4.

- WSE
, -
. MSMQ COM+

. Remoting
IIS / MSMQ, ,
.

189

10.

10.

.

10.1.

.NET Framework
. . 10.1 (
Remoting / MSMQ). RPC . 10.1
Windows NT 5.* ,
.
.

WS

Remoting

MSMQ
MSMQ
MSMQ

COM+

IIS

HTTP

RPC

TCP

UDP

IP

10.1.

190

10.
10.2.


. COM+
(JIT-activation). .NET
Remoting :

HTTP, SOAPFormatter, IIS ;

TCP, BinaryFormatter, IIS


;

TCP, BinaryFormatter, IIS


.

,
:

WAN ;

AD Active Directory LAN/VPN;

VPN
.

10.1.

MSMQ

AD

COM+ (JIT)

AD

Remoting/HTTP/SOAP/IIS

WAN

Remoting/TCP

VPN

Remoting, .

VPN

WAN

WS

191

10.
.
1. - .
2. MSMQ (
), ( Microsoft)
.
3. Remoting :
,
,
CLI.
10.1 ,
.NET .NET Remoting.
,
, .

.
1. .Net Remoting
,
IIS. IIS Remoting
, WSE
-.
2.

MSMQ

Active Directory
Remoting COM+. MSMQ IIS
.
3. Enterprise Services / COM+
, ,
. ,
.

192

10.
,
.
4. - ASP.NET / WSE
. - ASP.NET
,
COM+.
.
. 10.2
,
, .
- (ASP.NET Remoting),
MSMQ HTTP.


MSMQ

MSMQ

WS

MSMQ
HTTP

MSMQ

COM+


MSMQ COM+
-
ASP.NET

WS

COM+

WS

-
Remoting

Remoting

WS

Remoting

10.2.

193

10.
10.3.

.NET Framework

.NET

Framework

2.0

,
.

(, WS COM+),
,
.

Remoting
.
.NET Framework , ,
,
.

194


1.

., . . .
. : . 2003 . 880 c.

2.

., ., . Microsoft .NET Remoting.


, 2003 . 384 .

3.

. C# . NET. C: -, 2002 . 800 .

4.

. COM+. : , 2001 . 464 .

5.

. -. XML, WSDL, SOAP UDDI. .: , 2002 .


256 .

: Microsoft
Microsoft Developer Network (MSDN),
http://msdn.microsoft.com.

195

I. COM+

I. COM+
.NET Framework 2.0
COM+,
COM+ regsvcs.exe. ,
.NET Framework
COM+. .

COM

COM+,

.NET

%systemroot%\system32\com\comadmin.dll.
.
sn /k comadmin.snk
tlbimp %Systemroot%\system32\com\comadmin.dll /keyfile:comadmin.snk
/out:interop.comadmin.dll /namespace:ComAdmin

COM-

CLR

interop.comadmin.dll,
ComAdmin.
interop.comadmin

COM+.
COM+, .
I.I COM+,
.

196

I. COM+
COM+

COM+
(Applications)

COM+

DCOM

(Components)


(InterfacesForComponents)


(MethodsForInterface)


c
COM+

(Roles)


(SubscriptionsForComponent)


(RolesForComponent)


(RolesForInterface)


(RolesForMethod)

I.I. COM+
LceUtils
. .
// SevaComLCE.cs
using System;
using ComAdmin;
namespace Seva.ComUtils
{
public static class LceUtils
{
//
public static void PermanentSubscription(string appName,
string subscriberName, string eventGuid, string interfaceGuid)
{
// COM+
COMAdminCatalog catalog = new ComAdmin.COMAdminCatalogClass();
ICatalogObject CatalogObject = null;
ICatalogCollection CompCollection = null, SubCollection = null;
// COM+
ICatalogCollection AppCollection = (ICatalogCollection)
catalog.GetCollection("Applications");
AppCollection.Populate();

197

I. COM+

//
for (int Counter = 0; Counter < AppCollection.Count; Counter++)
{
CatalogObject = (ICatalogObject) AppCollection.get_Item(Counter);
if ((String)CatalogObject.Name == appName)
{
//
CompCollection = (ICatalogCollection)
AppCollection.GetCollection("Components",
CatalogObject.Key);
CompCollection.Populate();
break;
}
}
if (CompCollection == null)
{
throw new ApplicationException(
String.Format("COM+ Application not found : [{0}]", appName));
}
//
for (int Counter = 0; Counter < CompCollection.Count; Counter++)
{
CatalogObject = (ICatalogObject) CompCollection.get_Item(Counter);
if ((String)CatalogObject.Name == subscriberName)
{
//
SubCollection = (ICatalogCollection)
CompCollection.GetCollection(
"SubscriptionsForComponent", CatalogObject.Key);
SubCollection.Populate();
break;
}
}
if (SubCollection == null)
{
throw new ApplicationException(
String.Format("Component not found : [{0}]", subscriberName));
}
//
CatalogObject = (ICatalogObject)SubCollection.Add();
CatalogObject.set_Value("EventCLSID", "{" + eventGuid + "}");
CatalogObject.set_Value("Name", "Permanent Subscription");
CatalogObject.set_Value("InterfaceID", "{" + interfaceGuid + "}");
CatalogObject.set_Value("Enabled", true);
//
SubCollection.SaveChanges();
} // Subscribe
} //LceUtils
} // Seva.ComUtils

198

II. ASP.NET IIS

II. ASP.NET IIS



- ASP.NET IIS. .NET
Framework 2.0 Windows XP SP2 Windows Server 2003
-
HttpListener HttpRuntime, IIS .
,
ASP.NET .
// SevaAspHost.cs
using System;
using System.IO;
using System.NET;
using System.Web;
using System.Web.Hosting;
using System.Text.RegularExpressions;
namespace Seva.AspHost
{
public class AspHost: MarshalByRefObject
{
private HttpListener listener;
private string virtualDir;
private string hostingDir;
public string VirtualDir
{
get {return virtualDir;}
}
public string HostingDir
{
get {return hostingDir;}
}
public static AspHost CreateHost(string[] prefixes, string aspVirtualDir,
string aspHostingDir)
{
if (!HttpListener.IsSupported)
{
throw new NotSupportedException(
" Windows XP SP2/Server 2003.");
}
AspHost host = (AspHost) ApplicationHost.CreateApplicationHost(
typeof(AspHost), aspVirtualDir, aspHostingDir);
host.Init(prefixes, aspVirtualDir, aspHostingDir);
return host;
}

199

II. ASP.NET IIS


public void Init(string[] prefixes, string aspVirtualDir,
string aspHostingDir)
{
virtualDir = aspVirtualDir;
hostingDir = aspHostingDir;
listener = new HttpListener();
foreach (string prefix in prefixes)
listener.Prefixes.Add(prefix);
}
public void Start()
{
listener.Start();
}
public void Stop()
{
listener.Stop();
}
public void ProcessRequest()
{
HttpListenerContext context = listener.GetContext();
HttpListenerWorkerRequest workerRequest =
new HttpListenerWorkerRequest(context, this);
HttpRuntime.ProcessRequest(workerRequest);
}
}
public class HttpListenerWorkerRequest: HttpWorkerRequest
{
private HttpListenerContext context;
private AspHost host;
public HttpListenerWorkerRequest(HttpListenerContext listenerContext,
AspHost aspHost)
{
context = listenerContext;
host = aspHost;
}
public override void EndOfRequest()
{
context.Response.OutputStream.Close();
context.Response.Close();
}
public override void FlushResponse(bool finalFlush)
{
context.Response.OutputStream.Flush();
}
public override string GetHttpVerbName()
{
return context.Request.HttpMethod;
}

200

II. ASP.NET IIS


public override string GetHttpVersion()
{
return string.Format("HTTP/{0}",
context.Request.ProtocolVersion.ToString());
}
public override string GetLocalAddress()
{
return context.Request.LocalEndPoint.Address.ToString();
}
public override int GetLocalPort()
{
return context.Request.LocalEndPoint.Port;
}
public override string GetQueryString()
{
return context.Request.Url.Query.TrimStart(new char[]{'?'});
}
public override string GetRawUrl()
{
return context.Request.RawUrl;
}
public override string GetRemoteAddress()
{
return context.Request.RemoteEndPoint.Address.ToString();
}
public override int GetRemotePort()
{
return context.Request.RemoteEndPoint.Port;
}
public override string GetUriPath()
{
return context.Request.Url.LocalPath;
}
public override void SendKnownResponseHeader(int index, string value)
{
context.Response.Headers[GetKnownResponseHeaderName(index)] = value;
}
public override void SendResponseFromMemory(byte[] data, int length)
{
context.Response.OutputStream.Write(data, 0, length);
}
public override void SendStatus(int statusCode, string statusDescription)
{
context.Response.StatusCode = statusCode;
context.Response.StatusDescription = statusDescription;
}
public override void SendUnknownResponseHeader(string name, string value)
{
context.Response.Headers[name] = value;
}

201

II. ASP.NET IIS


public override void SendResponseFromFile(IntPtr handle, long offset,
long length)
{
}
public override void SendResponseFromFile(string filename, long offset,
long length)
{
}
public override string GetAppPath()
{
return host.VirtualDir;
}
public override string GetAppPathTranslated()
{
return host.HostingDir;
}
public override string GetUnknownRequestHeader(string name)
{
return context.Request.Headers[name];
}
public override string GetKnownRequestHeader(int index)
{
switch (index)
{
case HeaderUserAgent:
return context.Request.UserAgent;
default:
return
context.Request.Headers[GetKnownRequestHeaderName(index)];
}
}
public override string GetFilePath()
{
string s = context.Request.Url.LocalPath;
Regex re = new Regex(@"^(.*\.as\wx)\/\w+$");
Match m = re.Match(s);
if (m.Success)
s = m.Groups[1].Value;
return s;
}
public override string GetFilePathTranslated()
{
string s = GetFilePath().Substring(host.VirtualDir.Length);
return host.HostingDir + s.Replace('/', '\\');
}
public override string GetPathInfo()
{
return context.Request.Url.LocalPath.Substring(GetFilePath().Length);
}
public override int ReadEntityBody(byte[] buffer, int size)
{
return context.Request.InputStream.Read(buffer, 0, size);
}
}
}

202

II. ASP.NET IIS

ASP- www
8080.
// AspServer.cs
using System;
using System.IO;
using Seva.AspHost;
class Program
{
static void Main(string[] args)
{
string[] prefixes = new string[]
{
"http://localhost:8080/", "http://127.0.0.1:8080/"
};
AspHost host = AspHost.CreateHost(prefixes, "/",
Directory.GetCurrentDirectory()+@"\www");
host.Start();
foreach (string s in prefixes)
Console.WriteLine(s);
while (true)
host.ProcessRequest();
}
}

ApplicationHost.CreateApplicationHost (
AspHost) , , .
make- ASP.NET.
all: ASPServer.exe
ASPServer.exe: *.cs AspHost.dll
csc /out:ASPServer.exe AspServer*.cs /r:AspHost.dll
AspHost.dll: SevaAspHost.cs AspHost.key
csc /out:ASPHost.dll /t:library SevaAspHost.cs /keyfile:AspHost.key
AspHost.key:
sn -k AspHost.key
install:
gacutil -i ASPHost.dll
if not exist www md www

nmake && nmake install www


ASP.NET aspx asmx.
203

III.

III.
, .NET Remoting,
.
FCL RijndaelManaged,
.
,
. Encrypt Decrypt

.
// SevaSecurityCipher.cs
using System;
using System.IO;
using System.Security.Cryptography;
namespace Seva.Security.Encryption
{
public class SymmetricEncryptor
{
public const int KeySize = 32;
public const int BlockSize = 32;
RijndaelManaged cipher = null;
public byte[] Key
{
get { return cipher.Key; }
set { cipher.Key = value; }
}
public SymmetricEncryptor()
{
cipher = CreateCipher();
cipher.GenerateKey();
}
public SymmetricEncryptor(byte[] key)
{
cipher = CreateCipher();
cipher.Key = key;
}

204

III.
public void SaveKey(string fileName)
{
using (FileStream file = new FileStream(fileName,
FileMode.Create, FileAccess.Write))
{
file.Write(Key, 0, Key.Length);
}
}
public void LoadKey(string fileName)
{
byte[] buffer = new byte[KeySize];
using (FileStream file = new FileStream(fileName,
FileMode.Open, FileAccess.Read))
{
file.Read(buffer, 0, KeySize);
}
Key = buffer;
}
public byte[] CreateEmptyIv()
{
return new byte[SymmetricEncryptor.BlockSize];
}
public byte[] EncryptMessage(byte[] plainText, out byte[] iv)
{
cipher.GenerateIV();
iv = cipher.IV;
ICryptoTransform transform = cipher.CreateEncryptor();
byte[] cipherText = transform.TransformFinalBlock(plainText,
0, plainText.Length);
return cipherText;
}
public byte[] DecryptMessage(byte[] cipherText, byte[] iv)
{
cipher.IV = iv;
ICryptoTransform transform = cipher.CreateDecryptor();
byte[] plainText = transform.TransformFinalBlock(cipherText,
0, cipherText.Length);
return plainText;
}
public void Encrypt(Stream input, Stream output)
{
byte[] iv = null;
byte[] buffer = new byte[input.Length];
input.Read(buffer, 0, buffer.Length);
buffer = EncryptMessage(buffer, out iv);
//
output.Write(iv, 0, iv.Length);
output.Write(buffer, 0, buffer.Length);
}

205

III.
public void Decrypt(Stream input, Stream output)
{
byte[] iv = CreateEmptyIv();
byte[] buffer = new byte[input.Length-iv.Length];
input.Read(iv, 0, iv.Length);
input.Read(buffer, 0, buffer.Length);
//
buffer = DecryptMessage(buffer, iv);
output.Write(buffer, 0, buffer.Length);
}
private RijndaelManaged CreateCipher()
{
RijndaelManaged cipher = new RijndaelManaged();
cipher.KeySize
cipher.BlockSize
cipher.Mode
cipher.Padding

=
=
=
=

KeySize * 8;
BlockSize * 8;
CipherMode.CBC;
PaddingMode.PKCS7;

return cipher;
}
}
}
// SevaSecurityCipher.cs

,
.
// makekey.cs
using System;
using System.IO;
using Seva.Security.Encryption;
class MainApp
{
public static void Main(string[] Args)
{
if (Args.Length != 1)
{
Console.WriteLine("usage: makekey <key_file>");
return;
}
SymmetricEncryptor encryptor = new SymmetricEncryptor();
encryptor.SaveKey(Args[0]);
}
}
// makekey.cs

.
csc MakeKey.cs SevaSecurityCipher.cs

206

Вам также может понравиться