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

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

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

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

意見交換

クローズ

34回答

1566閲覧

ソケット通信のconnectの頻度について

jmdajmw

総合スコア335

C#

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

1グッド

1クリップ

投稿2024/07/26 02:43

1

1

テーマ、知りたいこと

装置制御PLCとの通信にソケット通信を使っています。
送受信する都度connectとshutdownをしています。
頻度としては200msec毎に4〜5回のconnectとshutdownを繰り返しています。
connectとshutdownは頻繁に行わない方が良いのでしょうか?

背景、状況

PLCとの通信プログラムをメインプログラムから分離してdllにする際1ビットの値を取得する関数内でconnectとshutdownを行うように作ってしまい、そのためメインプログラムから1ビットの値を取得する都度connectとshutdownをしてしまうプログラムになっています。

fana👍を押しています

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

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

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

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

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

回答34

#1

otn

総合スコア85630

投稿2024/07/26 10:38

connectとshutdownは頻繁に行わない方が良いのでしょうか?

別にかまいません。
connectしっぱなしのほうが、処理が減るので、CPUやハブの消費電力が減る(温度に影響)とか、
その分処理が速くなるかもというメリットはありますが、
(実際に速くなるかどうかは全体の処理内容次第。間にあるネット機器の数が多いほど効く)
そこまで気にしないなら、プログラムロジックが簡単な方がメンテしやすいしバグも出にくいです。

処理速度を少しでも速くしたいという要件があり、コネクト処理のオーバヘッドの影響が大きいと判断したのなら、
繋ぎっぱなしにするようなプログラム修正に取り組むのでしょうね。

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

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

#2

退会済みユーザー

退会済みユーザー

総合スコア0

投稿2024/07/26 10:51

そもそも前提があまりにもあやふやなので、意見を書きたくなかったのですが、書いちゃった人がいるので一応懸念点を書いておきます。connectとshutdownは頻繁に行わない方が良いです。

https://learn.microsoft.com/ja-jp/troubleshoot/windows-client/networking/tcp-ip-port-exhaustion-troubleshooting

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

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

#3

jmdajmw

総合スコア335

投稿2024/07/26 10:55

#1
ありがとうございます。
今のままにしておきます。

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

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

#4

jmdajmw

総合スコア335

投稿2024/07/26 11:00

#2
スタンドアローンの測定装置です。
諸々の機器をPLCで制御し、PLCへの指令やPLCからの値の取得にソケット通信を使っています。
その場合でもその懸念点はあるのでしょうか?

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

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

#5

otn

総合スコア85630

投稿2024/07/26 11:03

なるほど。この質問者のケースを離れて、一般論として回答すると仰るとおりでしょうね。
そこまで考えませんでした。

問題が起こっているなら書いてあるはずなので、
「今動いていて、何の障害も起こっていない」という前提で回答しています。
現状動いているのなら、ポートの枯渇は起こっていないということかと思います。

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

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

#6

jmdajmw

総合スコア335

投稿2024/07/26 11:15

#5
夜通し動かし続けると朝にはアプリが落ちていることがあります。
少なく見積もって毎秒5回として1時間に18000回connectとshutdownを繰り返しているとするとその懸念点が原因の可能性もあるでしょうか?

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

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

#7

退会済みユーザー

退会済みユーザー

総合スコア0

投稿2024/07/26 11:19

#4
スタンドアローンの測定装置というだけでは全然フワッとしていて何の説明にもなっていません

例えば組み込み制御よりの開発では、今起こっていないからいいなどの判断は多分ないと思いますよ
意識としては、

設計上問題が起こりえないから平気
→それでも十二分に確認
→万全の品質を保証できたら製品として出荷

のような感じだと思います

別に多かれ少なかれなんでもそうだと思いますが…

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

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

#8

jmdajmw

総合スコア335

投稿2024/07/26 11:50

#7
なんで?
今起こっている問題は「夜通し動かし続けると翌朝落ちて画面が消えていることがある。タスクマネージャーで見ても消えている。ログを見ても何が起こったのかよくわからない。」という問題です。
その問題の原因になり得るなら直しますが関係ないなら放置ですね。

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

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

#9

jmdajmw

総合スコア335

投稿2024/07/26 11:54

今夜から月曜日の朝まで連続運転するのでまた落ちていたら試しにconnectは起動時だけにしてみますが、、、

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

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

#10

退会済みユーザー

退会済みユーザー

総合スコア0

投稿2024/07/26 12:35

#8
考え方が逆です。
絶対にならないと言い切れない限り、あなたの責任になるので、懸念点は潰さないといけないんですよ?
そして仕事でやっていて、指摘された懸念点があるなら、あなたが責任を持って関係あるかどうかを言い切らないといけません

「問題の原因になり得るか分からない」のに「放置です」と言われたら、私が客なら交替してもらいます

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

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

#11

jmdajmw

総合スコア335

投稿2024/07/26 12:41

#10
仕事は仕事ですが、、、
私を交替させる権限を持った客は存在しません。

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

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

#12

退会済みユーザー

退会済みユーザー

総合スコア0

投稿2024/07/26 12:59

#11
じゃあ誰から受けた仕事なんでしょうね。。。
別の人か別の会社に出せば交替できないはずないですが。。。

あと主旨はコチラです

考え方が逆です。
絶対にならないと言い切れない限り、あなたの責任になるので、懸念点は潰さないといけないんですよ?
そして仕事でやっていて、指摘された懸念点があるなら、あなたが責任を持って関係あるかどうかを言い切らないといけません

そんな無責任な仕事をしていたら本当に仕事なくなりますよ。

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

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

#13

matukeso

総合スコア1666

投稿2024/07/27 01:34

その使い方だとtcpの必要、というか利点がないような。udpの方が適切なのでは。

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

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

#14

退会済みユーザー

退会済みユーザー

総合スコア0

投稿2024/07/27 02:51

編集2024/07/27 03:10

どれだけ離れているのか知りませんが、到達保証や順序保証のないUDPを、TCPすらまともに使えてなさそうな人に使わせるのは不安しかない気もしますね


いいねとかしないでもらえますか?どれだけ離れているのかを含む、どちらが適しているのかを含む全ての判断材料を持ってるのはあなただけですよ
もし順序保証があり、ロスがありえないなら、UDPの方が適しているのは明らかです
そしてより良い選択・判断をする責任を持つのはあなたです
仕事なので

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

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

#15

jmdajmw

総合スコア335

投稿2024/07/29 06:04

connectを起動時のみにしたら動かなくなったのでやめました。

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

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

#16

otn

総合スコア85630

投稿2024/07/29 12:01

今起こっている問題は「夜通し動かし続けると翌朝落ちて画面が消えていることがある。タスクマネージャーで見ても消えている。ログを見ても何が起こったのかよくわからない。」という問題です。

なんと。障害が起こっていたのですね。
ポート枯渇していればconnectが失敗すると思うので、例外を握りつぶしていない限りは、その例外が起こったというメッセージががログに出そうですけど、そもそもログを書いてないとかですかね?あるいは例外を握りつぶしている?

それはそれとして、ポート枯渇が起こっているかどうかは、一定時間毎に、
echo $(date "+%F %T") $(netstat|grep "^tcp"|wc -l) >> どこかのファイル
とか実行してTCPの使用ポート数の変化を見れば見当つきそうです。

connectを起動時のみにしたら動かなくなったのでやめました。

「プログラムをちゃんと書き換えることに掛かる負荷」に対して「翌朝落ちてて画面が消えている事による困り具合」が無視できる程度なら、それでも良いと思います。

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

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

#17

jmdajmw

総合スコア335

投稿2024/08/02 07:00

#16
通信エラーが起きたらログを出力するようにしたところ丸1日動かした後、通信エラーが発生して停止しました。

echo $(date "+%F %T") $(netstat|grep "^tcp"|wc -l) >> どこかのファイル

↑これは意味がよくわからなかったのですが、通信関数にlockを追加したところ意味不明な動作をしています。
lock中に他のスレッドから通信関数が呼ばれるとそこで待つのではなく何もせずにその関数を抜けているような感じです。

そういうものでしょうか?

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

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

#18

jmdajmw

総合スコア335

投稿2024/08/02 08:16

マルチスレッドがよくわかりません。
PLCからデータを取得する関数とPLCにデータを書き込む関数を互いに同時には動かないよう関数の入口で待機して欲しいのですが、どうやって実装すれば良いですか?

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

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

#19

YAmaGNZ

総合スコア10450

投稿2024/08/02 08:18

どのようにコーディングしたかも分からないのに「そういうもの」も何もないでしょう。
というか異常の切り分けも出来ていない話なのに順番がおかしいです。
しっかり異常の切り分けをしてこういうコードでこういうエラーが発生するといった感じでしっかり事象を纏めてから質問すべきかと思います。
意見交換ですと抽象的な話になりますしね。

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

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

#20

otn

総合スコア85630

投稿2024/08/02 10:04

↑これは意味がよくわからなかったのですが

なんと。それは予想外。
ではこの件は忘れて下さい。これは余談で、本筋は下記です。

ポート枯渇していればconnectが失敗すると思うので、例外を握りつぶしていない限りは、その例外が起こったというメッセージががログに出そうですけど、そもそもログを書いてないとかですかね?あるいは例外を握りつぶしている?

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

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

#21

jmdajmw

総合スコア335

投稿2024/08/02 10:46

#20
catchの中が空だったのでログを出力したところ数時間動かした後、通信エラーが連発し、通信不能になりました。

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

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

#22

jmdajmw

総合スコア335

投稿2024/08/02 11:30

編集2024/08/02 11:51

#19
やりたいことは↓こんな感じです。

C#

1using System; 2using System.Collections.Generic; 3using System.ComponentModel; 4using System.Data; 5using System.Drawing; 6using System.Linq; 7using System.Text; 8using System.Threading; 9using System.Threading.Tasks; 10using System.Windows.Forms; 11using Timer = System.Threading.Timer; 12 13namespace WindowsFormsApp2 14{ 15 public partial class Form1 : Form 16 { 17 public Form1() 18 { 19 InitializeComponent(); 20 } 21 22 private static object lockObject = new object(); 23 private static int Counter = 0; 24 public delegate void DelegateUpdateText(); 25 private static Timer timer; 26 27 private void Form1_Load(object sender, EventArgs e) 28 { 29 timer = new Timer(TimerCallback); 30 timer.Change(0, 200); 31 } 32 33 private void button1_Click(object sender, EventArgs e) 34 { 35 lock (lockObject) 36 { 37 MessageBox.Show("待機中");// ソケット通信のデータ送信の代わり 38 } 39 } 40 void TimerCallback(object state) 41 { 42 updateText(); 43 } 44 45 private void updateText() 46 { 47 this.Invoke(new DelegateUpdateText(this.OnUpdateText)); 48 } 49 private void OnUpdateText() 50 { 51 lock (lockObject) 52 { 53 Counter++; 54 label1.Text = Counter.ToString();// ソケット通信の受信の代わり 55 } 56 } 57 } 58}

待機中はカウントアップが止まってほしいのに止まってくれません。

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

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

#23

YAmaGNZ

総合スコア10450

投稿2024/08/02 12:27

lockステートメントは複数のスレッドでの排他処理に使用するもので同一スレッドでlockしてもロックされません。
提示されたコードですと、MessageBoxを表示しているスレッドとOnUpdateTextはOnUpdateTextがInvokeで呼び出されているために同一のスレッドとなっていてlockがかかりません。

C#

1 private void updateText() 2 { 3 lock (lockObject) 4 { 5 this.Invoke(new DelegateUpdateText(this.OnUpdateText)); 6 } 7 } 8 private void OnUpdateText() 9 { 10 Counter++; 11 label1.Text = Counter.ToString();// ソケット通信の受信の代わり 12 }

といった感じでInvokeする前にlockすれば思った動作になるかと思います。

ただ現在のやりとりが意見交換の主題から外れているので新たに質問すべきだと思います。

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

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

#24

otn

総合スコア85630

投稿2024/08/02 12:49

catchの中が空だったので

やはり、例外を握りつぶしていたのですね。それでは原因究明など出来ません。

通信エラーが連発し、通信不能になりました。

エラーメッセージを見ないとコメントのしようがないです。

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

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

#25

jmdajmw

総合スコア335

投稿2024/08/02 13:25

#23
ありがとうございます。
やっと意味がわかりました。
これで来週の月曜日には問題が解消すると思います。

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

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

#26

jmdajmw

総合スコア335

投稿2024/08/02 13:27

#24

エラーメッセージを見ないとコメントのしようがないです。

エラーメッセージは会社のPCを見ないとわかりません。

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

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

#27

jmdajmw

総合スコア335

投稿2024/08/05 06:09

lockしたらフリーズしました。
デッドロックでしょうか?

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

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

#28

YAmaGNZ

総合スコア10450

投稿2024/08/05 06:27

私は超能力者じゃないので分かりません

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

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

#29

jmdajmw

総合スコア335

投稿2024/08/05 07:36

フリーズは解消しましたがSendとReceiveがごちゃごちゃになって実行されているようです。
1回のReceiveで2回分のSendの応答が送られてきたりしています。
毎回Connectとshutdownをすればごちゃごちゃにはならないものの数日動かし続けると通信エラーになることがあります。

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

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

#30

fana

総合スコア11942

投稿2024/08/05 08:19

(横から便乗質問の形になり恐縮ですが)
#23 のコードに対する疑問なのですが……
lock 中にスレッド切り替えるような処理って危なそうに見えるのですが,どうなのでしょう?

(UI ではないスレッドで実施されていると思われる)updateText() 内での lock の直後に
UI スレッド側が lock に達して待ち状態に入った場合,
その状態での Invoke って可能なのでしょうか? 
(ここでデッドロックする?)

lock 中には排他すべき処理(通信処理)だけを行うようにして,
その他のこと(何かしら UI スレッドで実施せねばならないと思われる作業)については
lock 解除後に Invoke (とか BeginInvoke ?)するのが 良い?/安心?/etc な可能性はないのでしょうか?

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

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

#31

YAmaGNZ

総合スコア10450

投稿2024/08/05 10:41

ご指摘の通り動作しなくなると思います。
私もlockステートメントの本来の使い方としては異なるスレッド(UIスレッドではないスレッド)間にて排他処理を行うといったものでありそのlock中の処理でスレッドを変更するという使い方をすべきではないと思っています。

しかし今回は、目的の動作が何故できないのかといった説明の為にサンプルを簡単に変更するとしたらということで
変更を提示しました。
デッドロックしてしまう注意点を提示できなかったのはこちらの落ち度となります。
申し訳ありませんでした。

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

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

#32

jmdajmw

総合スコア335

投稿2024/08/05 11:10

家に帰ってこんな感じのコードを書いてみたらなんとなく期待通りに?動いています。

C#

1using System; 2using System.Collections.Generic; 3using System.ComponentModel; 4using System.Data; 5using System.Drawing; 6using System.Linq; 7using System.Text; 8using System.Threading; 9using System.Threading.Tasks; 10using System.Windows.Forms; 11using Timer = System.Threading.Timer; 12 13namespace WindowsFormsApp2 14{ 15 public partial class Form1 : Form 16 { 17 public Form1() 18 { 19 InitializeComponent(); 20 } 21 22 private static object lockObject = new object(); 23 private static int Counter = 0; 24 private static int Counter2 = 0; 25 public delegate void DelegateUpdateText(); 26 private static Timer timer; 27 private static Timer timer2; 28 29 private void Form1_Load(object sender, EventArgs e) 30 { 31 timer = new Timer(TimerCallback); 32 timer.Change(0, 200); 33 } 34 35 private void button1_Click(object sender, EventArgs e) 36 { 37 timer2 = new Timer(TimerCallback2); 38 timer2.Change(0, 200); 39 } 40 void TimerCallback(object state) 41 { 42 timer.Change(0xFFFFFFFF, 0xFFFFFFFF); 43 UpdateText(); 44 timer.Change(200, 200); 45 } 46 47 private void UpdateText() 48 { 49 lock (lockObject) 50 { 51 this.Invoke(new DelegateUpdateText(this.OnUpdateText)); 52 } 53 } 54 private void OnUpdateText() 55 { 56 Counter++; 57 label1.Text = Counter.ToString();// ソケット通信の受信の代わり 58 } 59 60 void TimerCallback2(object state) 61 { 62 timer2.Change(0xFFFFFFFF, 0xFFFFFFFF); 63 UpdateText2(); 64 timer2.Change(200, 200); 65 } 66 67 private void UpdateText2() 68 { 69 lock (lockObject) 70 { 71 this.Invoke(new DelegateUpdateText(this.OnUpdateText2)); 72 } 73 } 74 private void OnUpdateText2() 75 { 76 Counter2++; 77 label2.Text = Counter2.ToString();// ソケット通信の送信の代わり 78 } 79 } 80}

なんか間違っているでしょうか?

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

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

#33

jmdajmw

総合スコア335

投稿2024/08/06 07:08

よくわかりませんがconnectしっぱなしは上手くいきません。

毎回connectする方式だと

netstat -nao | find "5000"

↑これを実行すると
TIME_WAIT が大量に出てきました。

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

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

#34

jmdajmw

総合スコア335

投稿2024/08/07 06:26

編集2024/08/07 06:27

https://ez-net.jp/article/FB/beofK19H/z5CwHgjxeJRA/

↑こちらを参考に短くしてみました。
大型連休中に止まらなければ良いのですが、、、

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

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

最新の回答から1ヶ月経過したため この意見交換はクローズされました

意見をやりとりしたい話題がある場合は質問してみましょう!

質問する

関連した質問