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

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

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

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

C#

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

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

Q&A

解決済

1回答

8520閲覧

C# WCFで大容量通信時のエラーに関して

kawauso

総合スコア56

WCF

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

C#

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

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

0グッド

0クリップ

投稿2019/09/05 00:26

編集2019/09/05 06:24

お世話になっております。

行いたいこと
同一PC内で2つのソフトウェア間でbyte配列の受け渡しを行いたいと思っています。
クライアント側から要求があった際にホスト側からbyte配列を送信する仕様にしたいと思っています。
配列の大きさは最大11,059,200byteを予定しています。

問題点
大量のデータを送信しようすると下記のようなエラーが出力されます。
最後にソースコードを記載しています。

エラー
Hostクラスのcallback.SendByteArr(arr);にて
System.ServiceModel.CommunicationException: 'パイプ パイプを閉じています。 (232, 0xe8) への書き込みエラーが発生しました。'
内部例外
PipeException: パイプ パイプを閉じています。 (232, 0xe8) への書き込みエラーが発生しました。

試したこと
エラー内容で調べたところ帯域不足の可能性があるなどの情報が得られたので
構成エディター ツール (SvcConfigEditor.exe)でソースコード>App.configのように帯域の値を大きくしてみました。このページなどを参考にしました。
→ 同じエラーが出力される

Host側のarrのサイズ変更
(1) var arr = new byte[500]; → ○
(2) var arr = new byte[65000]; → ○
(3) var arr = new byte[65500]; → ×
上記の(3)よりデフォルトの帯域最大値である65535より小さい値でも同一のエラーが出力されることが分かりました。
これにより帯域以外に原因があるのではと考えました。

質問
・エラーの原因・解決策などありましたら教示いただけないでしょうか。
・また、WCF以外にプロセス間で大量データをやりとりする手法があれば教えて頂ければ幸いです。

ソースコード

C#

1 // サーバー・クライアント共通インターフェース 2 [ServiceContract(CallbackContract = typeof(ICallback))] 3 internal interface IHost 4 { 5 [OperationContract(IsOneWay = true)] 6 void ByteArrRequest(); 7 } 8 9 [ServiceContract] 10 internal interface ICallback 11 { 12 [OperationContract(IsOneWay = true)] 13 void SendByteArr(byte[] bs); 14 }

C#

1 // ホスト側 2 [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple, UseSynchronizationContext = false)] 3 public class Host : IHost 4 { 5 public void ByteArrRequest() 6 { 7 Console.WriteLine("[HOST]: CLIENTから要求あり"); 8 9 var callback = OperationContext.Current.GetCallbackChannel<ICallback>(); 10 11 var arr = new byte[65500]; 12 callback.SendByteArr(arr); // ★ここでエラーが出力される 13 } 14 } 15 16 ServiceHost sh; 17 public MainWindow() 18 { 19 InitializeComponent(); 20 21 const string addr = "net.pipe://localhost/test1"; 22 var binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None); 23 // 追記1(解決策) 24 binding.MaxReceivedMessageSize = 64000000; 25 binding.MaxBufferSize = 64000000; 26 var readerQuotas = new XmlDictionaryReaderQuotas(); 27 readerQuotas.MaxArrayLength = 64000000; 28 readerQuotas.MaxStringContentLength = 64000000; 29 readerQuotas.MaxDepth = 32; 30 binding.ReaderQuotas = readerQuotas; 31 // 追記1ここまで 32 sh = new ServiceHost(typeof(Host)); 33 sh.AddServiceEndpoint(typeof(IHost), binding, addr); 34 sh.Open(); 35 }

C#

1 // クライアント側 2 class Callback : ICallback 3 { 4 public void SendByteArr(byte[] message) 5 { 6 Console.WriteLine(message.Length); 7 } 8 } 9 10 public MainWindow() 11 { 12 InitializeComponent(); 13 14 const string addr = "net.pipe://localhost/test1"; 15 var binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None); 16 // 解決策 17 binding.MaxReceivedMessageSize = 64000000; 18 binding.MaxBufferSize = 64000000; 19 var readerQuotas = new XmlDictionaryReaderQuotas(); 20 readerQuotas.MaxArrayLength = 64000000; 21 readerQuotas.MaxStringContentLength = 64000000; 22 readerQuotas.MaxDepth = 32; 23 binding.ReaderQuotas = readerQuotas; 24 // 解決策ここまで 25 var host = DuplexChannelFactory<IHost>.CreateChannel(new InstanceContext(new Callback()), binding, new EndpointAddress(addr)); 26 27 host.ByteArrRequest(); 28 }

↓ App.config(ホスト・クライアント共に同一内容)

XAML

1 <system.serviceModel> 2 <bindings> 3 <netNamedPipeBinding> 4 <binding name="NewBinding0" closeTimeout="00:20:00" openTimeout="00:20:00" 5 receiveTimeout="00:20:00" sendTimeout="00:20:00" maxBufferSize="64000000" 6 maxReceivedMessageSize="64000000"> 7 <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="64000000" 8 maxBytesPerRead="64000000" /> 9 </binding> 10 </netNamedPipeBinding> 11 </bindings> 12 <behaviors> 13 <endpointBehaviors> 14 <behavior name="NewBehavior0"> 15 <dataContractSerializer maxItemsInObjectGraph="10000000" /> 16 </behavior> 17 </endpointBehaviors> 18 <serviceBehaviors> 19 <behavior name="MyBehavior"> 20 <dataContractSerializer maxItemsInObjectGraph="100000000" /> 21 <serviceMetadata httpGetEnabled="true" /> 22 <serviceDebug includeExceptionDetailInFaults="true" /> 23 </behavior> 24 </serviceBehaviors> 25 </behaviors> 26 </system.serviceModel>

環境
C# .Net F/W 4.6.1
WPF

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

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

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

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

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

hihijiji

2019/09/05 01:37

sh = new ServiceHost(typeof(Host)); のshはどこにあるのかコードで示してください。
kawauso

2019/09/05 01:59

ホスト側のソースコードを修正しました。 MainWindow()内でshを宣言してもエラー内容は同一でした。
hihijiji

2019/09/05 02:07

そのコードで検証しているとしたら、後始末をしていないので繰り返すうちに不具合は出てきそうですね。
kawauso

2019/09/05 02:16

配列を送信できるのか試したかった為、このようなコードで試しています。 ホスト側起動→クライアント側起動の初回通信で必ず質問文のエラーが出力されます。 修正するにあたってヒントなどはないでしょうか。よろしくお願いします。
moredeep

2019/09/05 02:44

WCFのプロトコルについてよく知らないので間違っているかもしれないのですが。。。 >上記の(3)よりデフォルトの帯域最大値である65535より小さい値 これはどうなんだろう?って思いました。 この帯域ってヘッダ等を含まず、データのみなのでしょうか? IPv4ヘッダやTCPヘッダでも20バイトあり、WCFでは呼ばれた先に(どのメソッドを実行すべきか等)指示する必要もあると思うので、65500がダメだから65536未満でもエラーになるというのは間違っている可能性があるんじゃないかなと。 WCFのヘッダサイズが分かれば、65536-ヘッダサイズで試してみれば早いのですが。
hihijiji

2019/09/05 03:01

とりあえずServiceHostのCloseとDisposeを呼んでから終了するようにするといいと思います。
kawauso

2019/09/05 03:10

ご回答ありがとうございます。 moredeepさん ヘッダサイズは不明でしたが、ヘッダを含んだ帯域がデフォルトで65535のようです。 ご指摘の通り帯域は関係ないというのは否定できなくなりました。 App.configにて帯域を大きな数値に設定していますが、同様のエラーが出力されます。 なにか不備など分かることはありますでしょうか。 hihijijiさん ClosingイベントでCloseメソッドを呼ぶようにしました。 (Disposeメソッドは実装されていない?ようでした) しかし、同様のエラーが出力されます。
hihijiji

2019/09/05 03:18

Disposeはないみたいですね、失礼しました。 あと NetNamedPipeBinding の MaxReceivedMessageSize などがApp.configで設定した値になっているか確認してください。
kawauso

2019/09/05 03:33

MaxReceivedMessageSize などはApp.configで設定した値になっておらず、デフォルト値の65536でした。 コードまたはApp.configで設定等が必要なのでしょうか。 プロジェクト作成時に生成されるApp.configにSvcConfigEditor.exeで追記しています。 <system.serviceModel>以外には<configSections>,<runtime>,<userSettings>が記述されています。
hihijiji

2019/09/05 05:07

それは後で考えるとして、コードでMaxReceivedMessageSizeを変更して解決したら自己解決にしてください。
kawauso

2019/09/05 06:16

質問文のコードに追記しました。 bindingの各プロパティは変更されていますが、結果は変わりませんでした。 maxItemsInObjectGraphなどもコードで変更したかったのですが、方法が分かりませんでした。
hihijiji

2019/09/05 06:19

クライアント側もなおしてね
kawauso

2019/09/05 06:25

クライアント側も変更したところ解決しました。 自己解決を投稿します。ありがとうございました。
guest

回答1

0

自己解決

ホスト・クライアント側でbindingMaxReceivedMessageSizeなどのプロパティなどを直接変更することで解決しました。
hihijijiさんありがとうございました。

C#

1 // ホスト・クライアント側に下記のコードを追加 2 binding.MaxReceivedMessageSize = 64000000; 3 binding.MaxBufferSize = 64000000; 4 var readerQuotas = new XmlDictionaryReaderQuotas(); 5 readerQuotas.MaxArrayLength = 64000000; 6 readerQuotas.MaxStringContentLength = 64000000; 7 readerQuotas.MaxDepth = 32; 8 binding.ReaderQuotas = readerQuotas;

投稿2019/09/05 06:30

kawauso

総合スコア56

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問