質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.36%
WCF

WCFは、.NET Frameworkの提供する機能の一つ。サービス指向アプリケーション構築のためのフレームワークです。ネットワークを通して、異なるコンピュータ上で動くソフトウェア間の通信が可能になります。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

TCP

TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。

Q&A

解決済

1回答

9529閲覧

Windowsサービスを用いたWCFサービスでクライアントとTCP通信する際の例外を回避したい2

paul

総合スコア21

WCF

WCFは、.NET Frameworkの提供する機能の一つ。サービス指向アプリケーション構築のためのフレームワークです。ネットワークを通して、異なるコンピュータ上で動くソフトウェア間の通信が可能になります。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

TCP

TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。

0グッド

1クリップ

投稿2017/02/23 05:23

編集2017/02/23 06:26

###前提・実現したいこと
WCFサービスを、Windowsサービスにホストさせて、クライアントとTCP通信したいと思い、下記の記事を参考に実装進めております。

How to: Host WCF in a Windows Service Using TCP

例外を発生することなく、正常にTCPでクラサバ通信を行いたいと考えています。

###発生している問題・エラーメッセージ

サービスクライアントインスタンスをオープンするときに、例外が発生してしまいます。

なお、リモート先のマシンはファイヤーウォールを有効にしていて、該当のポート50000番(50000という数字は一例です)について例外設定(送受信ともに許可)しています。
そして、ポイントはファイヤーウォールを無効にすると例外が発生せず、正常にやり取りができていることです。

Service1Client client = null; string address = "net.tcp://<RemoteMachineName>:50000/MyService"; client = new Service1Client ("netTcpMyEndpoint", address); client.Open(); // <-- ここで例外 'System.Net.Sockets.SocketException'発生 // MyServiceClientはSystem.ServiceModel.ClientBase<TestProject.MyServiceReference.IService1>を継承し、 // TestProject.DebugWcfServiceReference.IService1を実装しているクラスです。 // これは Visual Studioにてサービス参照追加をした際に、自動で生成されるクラスです。

下記の例外が発生します。

<メッセージ> 'System.Net.Sockets.SocketException' 例外メッセージ : ”ホスト <RemoteMachineName> に対する DNS エントリが存在しません。” <トレース> 例外がスローされました: 'System.Net.Sockets.SocketException' (System.dll の中) 例外がスローされました: 'System.ServiceModel.EndpointNotFoundException' (System.ServiceModel.dll の中) 例外がスローされました: 'System.Reflection.TargetInvocationException' (mscorlib.dll の中) 例外がスローされました: 'System.ServiceModel.EndpointNotFoundException' (mscorlib.dll の中)

###Windowsサービスクラス

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Linq; using System.ServiceModel; using System.ServiceProcess; using System.Text; using System.Threading.Tasks; using WcfServiceLibrary1; namespace WindowsService1 { public partial class Service : ServiceBase { internal static ServiceHost myServiceHost = null; public Service() { InitializeComponent(); } protected override void OnStart(string[] args) { try { if (myServiceHost != null) { myServiceHost.Close(); } myServiceHost = new ServiceHost(typeof(Service1)); myServiceHost.Open(); } catch (Exception ex) { Console.WriteLine(ex.Message); Console.WriteLine(ex.StackTrace); throw; } } protected override void OnStop() { try { if (myServiceHost != null) { myServiceHost.Close(); myServiceHost = null; } } catch (Exception ex) { Console.WriteLine(ex.Message); throw; } } } }

###ホスト側のApp.Config

<?xml version="1.0" encoding="utf-8" ?> <configuration> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" /> </startup> <appSettings> <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" /> </appSettings> <system.web> <compilation debug="true" /> </system.web> <!-- サービス ライブラリ プロジェクトの展開時に、構成ファイルの内容をホストの app.config ファイルに追加する 必要があります。System.Configuration は、ライブラリの構成ファイルをサポートしていません。 --> <system.serviceModel> <bindings> <netTcpBinding> <binding name="netTcpServerBinding" portSharingEnabled="true"> <security mode="None"/> </binding> </netTcpBinding> </bindings> <services> <service name="WcfServiceLibrary1.Service1"> <endpoint address="" binding="netTcpBinding" bindingConfiguration="netTcpServerBinding" name="netTcpMyEndpoint" contract="WcfServiceLibrary1.IService1"> <identity> <dns value="localhost" /> </identity> </endpoint> <endpoint address="mex" binding="mexTcpBinding" bindingConfiguration="" contract="IMetadataExchange" /> <host> <baseAddresses> <add baseAddress="net.tcp://localhost:50000/Service1" /> </baseAddresses> </host> </service> </services> <behaviors> <serviceBehaviors> <behavior> <!-- メタデータ情報の開示を避けるには、 展開する前に下の値を false に設定します --> <serviceMetadata httpGetEnabled="False" httpsGetEnabled="False"/> <!-- デバッグ目的で障害発生時の例外の詳細を受け取るには、 下の値を true に設定します。例外情報の開示を避けるには、 展開する前に false に設定します --> <serviceDebug includeExceptionDetailInFaults="False" /> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> </configuration>

###実試したこと
・上記の参考サイトのコードにおけるService1というクラス名が、WCFサービスとWindowsサービスで重複していたので、WindowsサービスのほうをServiceに名前変更しております。
・ファイヤーウォールの例外設定の変更
→ TCP 0-60000 を送受信許可、UDP 53を送受信許可
→ UDP 0-60000 を送受信許可 ← 「サービスクライアントインスタンスをオープンするときに、例外が発生」という問題は解決されました

###補足情報(言語/FW/ツール等のバージョンなど)
C# 6.0
Visual Studio 2015

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

ファイアウォールでDNSへのアクセス(TCP/UDP53ポート等)をブロックしてたりしませんか?

投稿2017/02/23 05:36

YAmaGNZ

総合スコア10469

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

paul

2017/02/23 05:43 編集

早速のご回答ありがとうございます。 TCPは試験的に全ポート開けてみて試していました。  「実施したこと」に書くべきでした。追記させていただきます。 ですが、UDPまではあけていませんでしたので、UDPの53番を許可してみました。 しかし結果は変わっていないように見受けられます。。。 ご回答ありがとうございます。
paul

2017/02/23 06:33 編集

YAmaGNZ様 ご報告します。 結論から言うと通信ができました。 先ほど、UDPのポート53のみを許可しましたが、0-60000の範囲で許可したところ、通信できるようになりました。 この結果から以下の2つほど疑問が生まれました。 ・TCP通信を行っているのに、なぜUDPの許可が必要であるのか。 ・一体何番のポートが問題の対象だったのか。(YAmaGNZ様がおっしゃるように、例外メッセージを見るに、DNS関係の問題なのかもしれないと指摘されてから感じましたが、DNSのポートは53番だと私も理解しています。しかし53番以外を開けた結果うまくいったように思います。) これらのことについてお分かりになる方がいらっしゃったらご教授願いたく思います。 「Windowsサービスを用いたWCFサービスでクライアントとTCP通信する際の例外を回避したい2」という問題は解決しましたため、本質問は解決です。 このページも解決としたいところですが、本質問が記載されていたほうがスムーズに回答を得られると判断しますので、本日中は上記疑問が解消するまでは未解決のままにします。 YAmaGNZ様、ご回答ありがとうございます。
YAmaGNZ

2017/02/23 07:32

net.tcp://<RemoteMachineName>:50000/MyService これでアクセスしようとすると、<RemoteMachineName>をIPアドレスに変換しようとDNSへの問い合わせが行われます。 DNSへの問い合わせは通常は速度を速くしようとUDPパケットにて行われます。 これがファイアウォールでUDPポートを開放しないとだめな理由となります。 また、ファイアウォールをどのように設定されたか分かりませんが、デフォルトで 「コアネットワーク - DNS(UDP送信)」の設定があると思うので、そちらのほうとの競合があったのではないかと思います。
paul

2017/02/23 07:58

YAmaGNZ様 再度ご回答ありがとうございます。 >net.tcp://<RemoteMachineName>:50000/MyService >これでアクセスしようとすると、<RemoteMachineName>をIPアドレスに変換しようとDNSへの問い合わせが行われます。 >DNSへの問い合わせは通常は速度を速くしようとUDPパケットにて行われます。 >これがファイアウォールでUDPポートを開放しないとだめな理由となります。 UDPが使用される理由と、DNS問い合わせが発生する理由、とても理解できました。 ありがとうございます! >また、ファイアウォールをどのように設定されたか分かりませんが、デフォルトで >「コアネットワーク - DNS(UDP送信)」の設定があると思うので、そちらのほうとの競合があったのではないかと思います。 こちらですが、競合=同ポートに対して重複した許可設定がある と解釈して話を進めますが、競合があったから通信ができなかったとは考えにくいと判断しています。 先ほど0-60000の範囲のポートをUDP送受信許可設定したところ通信ができたとご報告しました。 確かにおっしゃる通り『「コアネットワーク - DNS(UDP送信)」の設定がある』のは事実で、有効になっていました。仮に競合がおこっているのであればUDP送受信で0-60000設定したとしても、53はこの0-60000の範囲にありますので、競合は解消されておりません。 おそらくこうであろう、という目星が一つ付きました。 先ほど展開しました、 ネットワークの DNS で使用されるポート(https://technet.microsoft.com/ja-jp/library/dd197515(v=ws.10).aspx)の記事を見ますと、DNSのUDPで使われる53ポートは”応答”の時に使用されるようで、”クエリ”は別の任意のポート番号が使われるようです。それが許可できていないことが問題だったのではないかと考えております。 そしてその任意のポート番号が0-60000の範囲に入っていたため、0-60000番ポート許可設定によって通信できるようになった。と考えております。 実際に、プロセスモニターでUDP通信を監視したところ、Open()した瞬間に 59901 56429 51839 54515 の4つが使われていることを確認しました。 TCPやUDPにおけるポート番号の一覧 https://ja.wikipedia.org/wiki/TCP%E3%82%84UDP%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B%E3%83%9D%E3%83%BC%E3%83%88%E7%95%AA%E5%8F%B7%E3%81%AE%E4%B8%80%E8%A6%A7 の 4 動的・プライベート ポート番号 (49152–65535) が使われているのだと判断しています。 49152–65535など、広範囲にポートをあけてしまうとファイヤーウォールの能力がかなり損なわれてしまうため、コーディング側で”クエリ”のポート番号を静的にできるようにし、指定し、その指定した番号をポートを開けるようにする術をこれから調査しようと思います。 本問題は解決したと考えます。YAmaGNZ様 どうもありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問