林 里奈
2022.11.22
TCP/IPServerのエラー
VstoneMagicを使用してCommUのプログラムを作成しております。
作成しているプログラムは、VC#製のコントローラからTCP/IP通信でコマンドを送信し、所定の動作を再生するというものです。
具体的には、TCP/IPサーバ初期化ブロックとTCP/IPサーバ受信ブロックを使用し、TCP/IPサーバ受信ブロックでコマンドに応じた動作を再生するような処理をしております。
 
コントローラから何度かコマンドを送信していると、その内、以下のようなエラーがコンソール上に表示されました。
 
> [Info][TCPIPServer]accept:/192.168.10.102:62192
> [Error][TCPIPServer]IOException
> ---------------------------------------------------------------------------------
> java.net.SocketException: Connection reset
> at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:113)
> at java.net.SocketOutputStream.write(SocketOutputStream.java:153)
> at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
> at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
> at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:295)
> at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:141)
> at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:229)
> at jp.vstone.network.TCPIPServer.waitRequest(TCPIPServer.java:72)
> at jp.co.mycommu.CCommUMain.tcp_ip(CCommUMain.java:1379)
> at jp.co.mycommu.CCommUMain.main(CCommUMain.java:1828)
> at main.main.main(main.java:41)
> ---------------------------------------------------------------------------------
> kill ` jps|grep "^[0-9]+ jar" |awk '{print $1}'`
> 中断します。
> exit
 
VC#製のコントローラにも、以下のようなエラーが表示され、プログラムが強制終了されます。
 
> 転送接続からデータを読み取れません: 接続済みの呼び出し先が一定の時間を過ぎても正しく応答しなかったため、接続できませんでした。または接続済みのホストが応答しなかったため、確立された接続は失敗しました。
 
通信が正常終了せず、例外処理が発生していることはわかるのですが、具体的な対処方法が分からず、困っております。
 
どのように対処すればよいか、ご教示いただけますと幸いです。よろしくお願いいたします。
回答
林 里奈
2022.11.22
参考になるかもしれませんので、VC#製のコントローラのTCP/IP通信の部分のソースコードを共有いたします。
 
private void Send(string data){
  TcpClient tcp = new TcpClient(txt_IP.Text, int.Parse(txt_Port.Text));
 
  NetworkStream ns = tcp.GetStream();
  ns.ReadTimeout = 5000;
  ns.WriteTimeout = 5000;
 
  byte[] sendBytes = Encoding.UTF8.GetBytes(data + " ");
  ns.Write(sendBytes, 0, sendBytes.Length);
 
  MemoryStream ms = new MemoryStream();
  byte[] resBytes = new byte[256];
  int resSize = 0;
  do{
    resSize = ns.Read(resBytes, 0, resBytes.Length);
    if (resSize == 0){
      break;
    }
    ms.Write(resBytes, 0, resSize);
  } while (ns.DataAvailable || resBytes[resSize - 1] != ' ');
 
  string resMsg = Encoding.UTF8.GetString(ms.GetBuffer(), 0, (int)ms.Length);
  ms.Close();
  resMsg = resMsg.TrimEnd(' ');
 
  ns.Close();
  tcp.Close();
}
Sotaサポート
2022.11.25
林様

お世話になります。Sotaサポートです。
申し訳ありませんが、原則としてユーザで作成されたプログラムのデバッグ・検証につきましてはサポート範囲外となり、詳細にお答えいたしかねますのでご了承ください。
ご質問では、一度も通信に成功しないという状況ではなく、数回通信に成功したのちに異常が発生する、という状況でしょうか?

TCP/IPブロックを用いて実装している場合、このブロックは半角英数を送受信する想定で、また改行コード( )を受信することでコマンドの区切りとみなし、接続先に「OK」の文字列を返します。また既定の時間でタイムアウトします。
作成された外部通信用のプログラムにおいて、この要件を満たさない挙動をしているために問題が発生していると思われます。
例えば、半角英数以外の文字列を含んでいる・改行コードの送信が行われていない(もしくは改行コードを間違えている)・タイムアウトを想定したつくりになっていないといったことが考えられます。

もしくは、VstoneMagic側の実装で、TCP/IPブロックを何度も繰り返し実行するようにしていると、通信に関する問題が発生する場合があります。基本的にはTCP/IPブロックは同一通信処理の開始・終了時のみ実行し、コマンドのやり取り毎に実行しなおさない作りにします。

TCP/IPブロックでうまく動作しない場合、JavaでのTCP/IP通信プログラムを独自に調査し、自由記述ブロックを用いて独自に通信処理を実装する方法も可能です。

何卒宜しくお願い致します。
林 里奈
2022.11.25
Sotaサポート様

ご回答いただきありがとうございます。

先に示したVC#製のコントローラのTCP/IP通信のソースコードですが、フォーム投稿時に記載した改行コードが消えておりました。
コントローラから送信されるコマンドは必ず末尾に改行コードが入るように作成しております。
また、コマンド送信後は、VstoneMagic側から送信される「OK[改行コード]」に基づき、接続を切断しております。

数回通信に成功したのちに異常が発生する状況でして、VstoneMagicとコントローラの処理状況を確認した範囲では、コマンド送信後、VstoneMagic側がacceptしたものの、何らかの異常が生じ、「OK[改行コード]」を送信しない/送信タイミングが遅れ、コントローラがタイムアウトしているという印象です。


> もしくは、VstoneMagic側の実装で、TCP/IPブロックを何度も繰り返し実行するようにしていると、通信に関する問題が発生する場合があります。基本的にはTCP/IPブロックは同一通信処理の開始・終了時のみ実行し、コマンドのやり取り毎に実行しなおさない作りにします。
こちらのご指摘ですが、コントローラからのコマンド送信に対応するため、
TCP/IPサーバ初期化ブロック→無限ループブロック→TCP/IPサーバ受信ブロック→コマンドに対応した動作のブロック
という構造のスレッドを走らせている状態ですが、それが問題ありということでしょうか?
Sotaサポート
2022.11.28
林様

お世話になります。Sotaサポートです。
TCP/IPブロックの使い方につきましては、添付図の事を示しておりました。
先の回答では、無限ループにて受信をし続ける場合、このように初期化ブロックはループ外に置いて初期化を繰り返さないようにするという意図で記載しておりました。


また、C#での実装につきまして、こちらで過去に実装したパターンでは、System.Text.Encoding.ASCII.GetBytesとしておりました。
関係するかわかりませんが、ご提示のソースはUTF8エンコードですので、一度ASCIIのエンコードでお試しいただくと状況が変わるかもしれません。
もしASCII文字以外を送受信されている場合は、それが原因の可能性があります。

また、それ以外の検証としては、プラットフォームなどにより改行コードの種類や自動的な付加といった挙動の違いがあることも考えられるため、改行コードを何パターンか試してみる( , , ,改行コードを付けない等)、受信バッファが想定せず蓄積していないか確認する/定期的に破棄する、等もお試しいただくと手掛かりになるかもしれません。

何卒宜しくお願い致します。
Sotaサポート
2022.11.28
上記回答で、改行コードに関する記載が空白になっておりましたので、再度該当箇所のみ記述します。
実際のソース内の改行コードは半角英数でご記載ください。

また、それ以外の検証としては、プラットフォームなどにより改行コードの種類や自動的な付加といった挙動の違いがあることも考えられるため、改行コードを何パターンか試してみる(¥n,¥r,¥r¥n,改行コードを付けない等)、受信バッファが想定せず蓄積していないか確認する/定期的に破棄する、等もお試しいただくと手掛かりになるかもしれません。
林 里奈
2022.11.28
Sotaサポート様

ご回答いただきましてまことにありがとうございます。

TCP/IPブロックは、図示いただきましたOKパターンで組んでおりましたので、ブロックの使い方としては問題なさそうなことを確認できたので、安心いたしました。

御社で過去に組まれたプログラムがASCII.GetBytesを使用されていたとのことですので、一度変更して確認してみます。

ご指摘いただきました通り、改行コードが使用プラットフォームにより、異なる可能性もございますので、一度確認してみます。
この質問に回答する
 

Page Top