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

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

新規登録して質問してみよう
ただいま回答率
85.50%
C#

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

Q&A

解決済

2回答

3531閲覧

名前付きパイプを双方向通信にしたい

trons

総合スコア20

C#

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

0グッド

1クリップ

投稿2018/10/04 02:29

前提・実現したいこと

https://qa.atmarkit.co.jp/q/3331
のコードを元にクライアント<=>サーバーの双方向通信に変更したい

ここに質問の内容を詳しく書いてください。

上記HPのコードを元に双方向に変更してみたのですが、サーバー側でのメッセージ受信後の
メッセージ送信時に「パイプが壊れています。」となり動作しません。

よろしくお願いします。

該当のソースコード

C#

1 2**サーバ側** 3ThreadState s = ThreadState.Stopped; 4 String pipeServerName = "pipeServerName"; 5 6 private void button1_Click(object sender, EventArgs e) 7 { 8 Thread t = new Thread(new ThreadStart(Method1)); 9 s = ThreadState.Running; 10 t.Start(); 11 } 12 13 private void Method1() 14 { 15 List<string> listInputDatas = new List<string>(); 16 string inputData = String.Empty; 17 18 while (true) 19 { 20 using (var pipeServer = new NamedPipeServerStream(pipeServerName, PipeDirection.InOut)) 21 { 22 using (var sr = new StreamReader(pipeServer)) 23 using (var sw = new StreamWriter(pipeServer)) 24 { 25 try 26 { 27 if (pipeServer.IsConnected == false) 28 { 29 pipeServer.WaitForConnection(); 30 } 31 32 //信号受信 33 inputData = sr.ReadLine(); 34 listInputDatas.Add((inputData)); 35 System.Diagnostics.Debug.Print(inputData); 36 } 37 catch (Exception Ex) 38 { 39 string ex = Ex.Message; 40 } 41 42 try 43 { 44 if (pipeServer.IsConnected == false) 45 { 46 pipeServer.WaitForConnection(); 47 } 48 49 sw.AutoFlush = true; 50 sw.Write("OK:" + inputData); //ここで例外発生「パイプが壊れています。」 51 sw.Flush(); 52 pipeServer.WaitForPipeDrain(); 53 } 54 catch(Exception Ex) 55 { 56 string ex = Ex.Message; 57 } 58 } 59 } 60 // その他終了判定など 61 if (s == ThreadState.Stopped) return; 62 } 63 } 64 65クライアント側 66// 名前かえました 67 String pipeServerName = "pipeServerName"; 68 69 private void btnStart_Click(object sender, EventArgs e) 70 { 71 var sb = new StringBuilder(); 72 73 // PIPEで送信する 74 using (var pipeClient = new NamedPipeClientStream("localhost", pipeServerName, PipeDirection.InOut, PipeOptions.None, System.Security.Principal.TokenImpersonationLevel.Impersonation)) 75 { 76 string inputData = String.Empty; 77 78 sb.AppendLine(DateTime.Now.ToString() + "\t" + textBox1.Text); 79 80 try 81 { 82 pipeClient.Connect(); 83 } 84 catch (Exception Ex) 85 { 86 87 } 88 89 using (var sw = new StreamWriter(pipeClient)) 90 { 91 sw.AutoFlush = true; 92 sw.Write(sb); 93 //sw.Flush(); 94 pipeClient.WaitForPipeDrain(); 95 } 96 97 98 using (var sr = new StreamReader(pipeClient)) 99 { 100 inputData = sr.ReadLine(); 101 } 102 103 } 104 } 105 106

補足情報(FW/ツールのバージョンなど)

VS2017
.net3.5
ここにより詳細な情報を記載してください。

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

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

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

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

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

guest

回答2

0

自己解決

おそらくですが、問題の原因が分かりました。
どうやら、プロセス浮きが原因で正常にパイプが接続できなかった模様です。
使用していたサーバー側のコードでは、常に次のメッセージを受信しているので
強制終了した際に、プロセスが浮く状態となっていました。

そのため、次の接続の際も、同じ接続用パイプ名で接続される状態のため
変な動きとなっていた模様です。

投稿2018/10/09 07:04

trons

総合スコア20

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

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

0

C#

1 using (var sw = new StreamWriter(pipeClient)) 2 { 3 sw.AutoFlush = true; 4 sw.Write(sb); 5 //sw.Flush(); 6 pipeClient.WaitForPipeDrain(); 7 } 8 9 // ここでパイプ閉じていないか? 10 11 using (var sr = new StreamReader(pipeClient)) 12 { 13 inputData = sr.ReadLine(); 14 } 15

クライアント側が using ブロックを2回に分けているので、
書き込んだあとブロックから抜ける時に、pipeClient.Dispose()が呼ばれて
パイプを閉じちゃっている気がします。(未確認です)

投稿2018/10/04 06:20

daisuke7

総合スコア1563

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

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

trons

2018/10/05 00:35

ご回答ありがとうございます。 指摘の内容を反映してみましたが、今度は同じように変更したクライアント側で同じ「パイプが壊れています。」が発生するようになってしまいました。 そもそも論にはなりますが、usingブロックでStreamを開放した場合、NamedPipeClientStreamなどの通信路側のStreamも一緒に閉じてしまうものなのでしょうか? ご存じであればおしえてください。 サーバー側 try { using (NamedPipeServerStream pipeServer = new NamedPipeServerStream(pipeServerName)) { pipeServer.WaitForConnection(); using (StreamReader sr = new StreamReader(pipeServer)) { using (StreamWriter sw = new StreamWriter(pipeServer)) { sw.AutoFlush = true; //信号受信 inputData = sr.ReadLine(); listInputDatas.Add((inputData)); System.Diagnostics.Debug.Print(inputData); sw.Write("OK:" + inputData); } } } } catch(Exception Ex) { string ex = Ex.Message; } クライアント側 try { using (NamedPipeClientStream namedPipeClientStream = new NamedPipeClientStream(pipeServerName)) { namedPipeClientStream.Connect(); using (StreamReader streamReader = new StreamReader(namedPipeClientStream)) { using (StreamWriter streamWriter = new StreamWriter(namedPipeClientStream)) { streamWriter.AutoFlush = true; streamWriter.WriteLine("aaaatest"); string inputData = streamReader.ReadLine(); Debug.WriteLine("\t\t\t◆◆◆◆◆◆" + inputData); MessageBox.Show(inputData); } } } } catch (Exception Ex) { string ex = Ex.Message; }
trons

2018/10/05 02:28

StreamWriterのusingを超えたのちに発生しております。 >StreamReader/StreamWriterのDispose()は、自分が使用しているstreamの >Close()を呼び出すはずです。 そうですか・・・。 ただそうすると、サーバー側で同じように例外が発生しないのが謎です。 参考HP https://ichiroku11.hatenablog.jp/entry/2016/07/28/204859 http://info-i.net/csharp-named-pipe また上記のusingで処理しているケースが多々ありますがusingを抜けた時点で 同じように例外が発生することになってしまうと思うのですが・・・ ちなみに、StreamReaderとStreamWriterのusingを削除して実行したところ 例外が発生しなくなりました。 よろしくお願いします。
daisuke7

2018/10/05 05:48

うーん、確かに。私が勘違いしているだけかもしれません。 そうであったらごめんなさい。 あともう一点気になったのは、sw.Write("OK:" + inputData); ではなく sw.WriteLine("OK:" + inputData); ではないか?ってあたりです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問