{"id":328,"date":"2007-03-09T20:36:52","date_gmt":"2007-03-09T18:36:52","guid":{"rendered":"http:\/\/www.puls200.de\/?p=328"},"modified":"2007-03-09T20:36:52","modified_gmt":"2007-03-09T18:36:52","slug":"remoting-fur-runaways","status":"publish","type":"post","link":"https:\/\/www.puls200.de\/?p=328","title":{"rendered":"Remoting f\u00fcr Runaways"},"content":{"rendered":"<p>Ein jeder, der sich noch vage an Dinge wie Corba erinnern kann wei\u00df, welch nette Idee hinter verteilten Objekten steckt: Ein Objekt wird als verteilt gekennzeichnet und wenn es mit einem geeigneten Parameter erzeugt wird, entsteht es auf einem anderen Rechner. F\u00fcr die Anwendung sieht es aber wie ein lokales Objekt aus, auf das ganz normal zugegriffen werden kann. H\u00f6rt sich toll an, f\u00fchrt in der Praxis jedoch zu allerlei Problemen, da die Zugriffe von den Launen des Netzwerks abh\u00e4ngig sind. Unter .NET wurde das Rad nochmal unter der Bezeichnung <em>remoting<\/em> neu erfunden.<\/p>\n<p>Der Zugriff auf ein entferntes Objekt ist einfach, ein paar Zeilen gen\u00fcgen:<\/p>\n<p><!--\n{\\rtf1\\ansi\\ansicpg\\lang1024\\noproof1252\\uc1 \\deff0{\\fonttbl{\\f0\\fnil\\fcharset0\\fprq1 Courier New;}}{\\colortbl;\\red0\\green0\\blue0;\\red0\\green0\\blue255;\\red0\\green255\\blue255;\\red0\\green255\\blue0??;\\red255\\green0\\blue255;\\red255\\green0\\blue0;\\red255\\green255\\blue0;\\red255\\green255\\blue255;??\\red0\\green0\\blue128;\\red0\\green128\\blue128;\\red0\\green128\\blue0;??\\red128\\green0\\blue128;\\red128\\green0\\blue0;\\red128\\green128\\blue0;\\red128\\green128\\blue128;??\\red192\\green192\\blue192;}??\\fs20 \\cf2 string\\cf0  url = \\cf2 string\\cf0 .Format(\\cf13 \"tcp:\/\/\\{0\\}:40506\/LPT_IO_Server\"\\cf0 ,\\par ??                    \\cf2 this\\cf0 .address);\\par ??                \\cf2 this\\cf0 .remoteObj = (\\cf10 BaseRemoteObject\\cf0 )\\par ??                    \\cf10 Activator\\cf0 .GetObject( \\cf2 typeof\\cf0 (\\cf10 BaseRemoteObject\\cf0 ), url);}\n--><\/p>\n<div style=\"font-family: Courier New; font-size: 9pt; color: black; background: white;\">\n<p style=\"margin: 0px;\"><span style=\"color: blue;\">string<\/span> url = <span style=\"color: blue;\">string<\/span>.Format(<span style=\"color: maroon;\">\"tcp:\/\/{0}:40506\/LPT_IO_Server\"<\/span>,<\/p>\n<p style=\"margin: 0px;\">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style=\"color: blue;\">this<\/span>.address);<\/p>\n<p style=\"margin: 0px;\"><span style=\"color: blue;\">this<\/span>.remoteObj = (<span style=\"color: teal;\">BaseRemoteObject<\/span>)<\/p>\n<p style=\"margin: 0px;\">&nbsp;&nbsp;&nbsp;<span style=\"color: teal;\">Activator<\/span>.GetObject( <span style=\"color: blue;\">typeof<\/span>(<span style=\"color: teal;\">BaseRemoteObject<\/span>), url);<\/p>\n<\/div>\n<p>Aber jetzt kommt das dicke Ende: Wenn der Server unten ist, bleibt die Anwendung beim Zugriff auf eines der Felder einfach h\u00e4ngen. Es gibt keine M\u00f6glichkeit, einen <em>connection timeout<\/em> einzustellen. Es dauert dann etwa 45 Sekunden, bevor eine <em>SocketException<\/em> anzeigt, da\u00df da was schiefging. Nicht gut f\u00fcr eine Anwendung mit Benutzerinteraktion. Man kann sich allerdings \"dreckig\" behelfen, indem man den Zugriff in einen eigenen Thread packt:<\/p>\n<p><!--\n{\\rtf1\\ansi\\ansicpg\\lang1024\\noproof1252\\uc1 \\deff0{\\fonttbl{\\f0\\fnil\\fcharset0\\fprq1 Courier New;}}{\\colortbl;\\red0\\green0\\blue0;\\red0\\green0\\blue255;\\red0\\green255\\blue255;\\red0\\green255\\blue0??;\\red255\\green0\\blue255;\\red255\\green0\\blue0;\\red255\\green255\\blue0;\\red255\\green255\\blue255;??\\red0\\green0\\blue128;\\red0\\green128\\blue128;\\red0\\green128\\blue0;??\\red128\\green0\\blue128;\\red128\\green0\\blue0;\\red128\\green128\\blue0;\\red128\\green128\\blue128;??\\red192\\green192\\blue192;}??\\fs20 \\cf11 \/\/ Ping the server in its own thread (so it doesn't block) \\par ??\\cf0             \\cf10 Exception\\cf0  setException = \\cf2 null\\cf0 ;\\par ??            \\cf10 DateTime\\cf0  now = \\cf10 DateTime\\cf0 .Now;\\par ??            System.Threading.\\cf10 Thread\\cf0  setThread = \\cf2 new\\cf0  System.Threading.\\cf10 Thread\\cf0 (\\cf2 delegate\\cf0 ()\\par ??            \\{\\par ??                \\cf2 try\\par ??\\cf0                 \\{\\par ??                    \\cf2 this\\cf0 .remoteObj.setValue(value);\\par ??                \\}\\par ??                \\cf2 catch\\cf0  (\\cf10 Exception\\cf0  ex)\\par ??                \\{\\par ??                    setException = ex;\\par ??                \\}\\par ??            \\});\\par ??            setThread.Start();\\par ??            \\cf2 if\\cf0  (setThread.Join((\\cf2 int\\cf0 )5000))\\par ??            \\{\\par ??                \\cf2 if\\cf0  (setException == \\cf2 null\\cf0 )\\par ??                \\{\\par ??                    \\cf11 \/\/ everything seems to be A-OK\\par ??\\cf0                     \\cf2 return\\cf0  \\cf2 true\\cf0 ;\\par ??                \\}\\par ??            \\}\\par ??            \\cf2 return\\cf0  \\cf2 false\\cf0 ;}\n--><\/p>\n<div style=\"font-family: Courier New; font-size: 8pt; color: black; background: white;\">\n<p style=\"margin: 0px;\"><span style=\"color: teal;\">Exception<\/span> setException = <span style=\"color: blue;\">null<\/span>;<\/p>\n<p style=\"margin: 0px;\"> System.Threading.<span style=\"color: teal;\">Thread<\/span> setThread = <span style=\"color: blue;\">new<\/span> System.Threading.<span style=\"color: teal;\">Thread<\/span>(<span style=\"color: blue;\"> delegate<\/span>()<\/p>\n<p style=\"margin: 0px;\">{<\/p>\n<p style=\"margin: 0px;\"> &nbsp; &nbsp; <span style=\"color: blue;\">try<\/span><\/p>\n<p style=\"margin: 0px;\"> &nbsp; &nbsp; {<\/p>\n<p style=\"margin: 0px;\"> &nbsp; &nbsp; &nbsp; &nbsp; <span style=\"color: blue;\">this<\/span>.remoteObj.setValue(value);<\/p>\n<p style=\"margin: 0px;\"> &nbsp; &nbsp; }<\/p>\n<p style=\"margin: 0px;\"> &nbsp; &nbsp; <span style=\"color: blue;\">catch<\/span> (<span style=\"color: teal;\">Exception<\/span> ex)<\/p>\n<p style=\"margin: 0px;\"> &nbsp; &nbsp; {<\/p>\n<p style=\"margin: 0px;\"> &nbsp; &nbsp; &nbsp; &nbsp; setException = ex;<\/p>\n<p style=\"margin: 0px;\"> &nbsp; &nbsp; }<\/p>\n<p style=\"margin: 0px;\"> });<\/p>\n<p style=\"margin: 0px;\"> setThread.Start();<\/p>\n<p style=\"margin: 0px;\"> <span style=\"color: blue;\">if<\/span> (setThread.Join((<span style=\"color: blue;\">int<\/span>)5000))<\/p>\n<p style=\"margin: 0px;\">{<\/p>\n<p style=\"margin: 0px;\">&nbsp; &nbsp; <span style=\"color: blue;\">if<\/span> (setException == <span style=\"color: blue;\">null<\/span>)<\/p>\n<p style=\"margin: 0px;\"> &nbsp; &nbsp; {<\/p>\n<p style=\"margin: 0px;\"> &nbsp; &nbsp; &nbsp; &nbsp; <span style=\"color: green;\">\/\/ everything seems to be A-OK<\/span><\/p>\n<p style=\"margin: 0px;\"> &nbsp; &nbsp; &nbsp; &nbsp; <span style=\"color: blue;\">return<\/span> <span style=\"color: blue;\">true<\/span>;<\/p>\n<p style=\"margin: 0px;\"> &nbsp; &nbsp; }<\/p>\n<p style=\"margin: 0px;\"> }<\/p>\n<p style=\"margin: 0px;\"> <span style=\"color: blue;\">return<\/span> <span style=\"color: blue;\">false<\/span>;<\/p>\n<\/div>\n<p>Das sieht nicht nur scheu\u00dflich aus sondern ist es auch. Aber so funktioniert es wenigstens. Jetzt bekommt man zwar auch eine Exception, aber asynchron. Ich finde es verwunderlich, da\u00df M$ hier auf ein besseres Interface verzichtet hat. Hat man sich aber soweit vorgew\u00fchlt, ist die remoting L\u00f6sung eine sehr praktische Sache. Keine Socketprogrammierung, kein Marshaling, einfach nur die Objekte deklariert und es kann losgehen.<br \/>\nMeine Anwendung sieht folgenderma\u00dfen aus: Auf bis zu 8 entfernten Rechnern laufen Windows Services, die die Datenkan\u00e4le des LPT Ports schalten k\u00f6nnen. Das Interface besteht aus einer einzigen Funktion: <em>setValue(byte)<\/em>. Auf einem zentralen Rechner kann man in einem Fenster alle entfernten Ports einzeln oder gleichzeitig schalten. Aus Remoting-Sicht ist dieser Rechner also der Client, der zu den entfernten Servern eine Verbindung aufbaut. Es ist wirklich ph\u00e4nomenal, wie schnell man zu einem Ergebnis kommt: H\u00e4tte ich o.g. Probleme nicht gehabt, w\u00e4re ich nach 5 Stunden (einschlie\u00dflich der Setups) fertig gewesen.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Ein jeder, der sich noch vage an Dinge wie Corba erinnern kann wei\u00df, welch nette Idee hinter verteilten Objekten steckt: Ein Objekt wird als verteilt gekennzeichnet und wenn es mit einem geeigneten Parameter erzeugt wird, entsteht es auf einem anderen &hellip; <a href=\"https:\/\/www.puls200.de\/?p=328\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0},"categories":[7,4],"tags":[],"_links":{"self":[{"href":"https:\/\/www.puls200.de\/index.php?rest_route=\/wp\/v2\/posts\/328"}],"collection":[{"href":"https:\/\/www.puls200.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.puls200.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.puls200.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.puls200.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=328"}],"version-history":[{"count":0,"href":"https:\/\/www.puls200.de\/index.php?rest_route=\/wp\/v2\/posts\/328\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.puls200.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=328"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.puls200.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=328"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.puls200.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=328"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}