TN3270e プロトコル

TN3270e プロトコルは、3270 ターミナルとプリンタ デバイスを Telnet を使用してエミュレートする手法です。Rumba® や Hummingbird の HostExplorer® fなどのターミナル エミュレーション ソフトウェアによってメインフレームに直接接続するために使用されます。

Telnet と似て、典型的な TN3270e セッションは 2 つの主要な部分から構成されます。

パート I:接続を確立する

TN3270e セッションの典型的な記録したスクリプトの最初の部分は次のようになります。

WebTcpipConnect(hWeb0, "10.19.111.201", 7230);
WebTcpipRecvExact(hWeb0, NULL, 3);
WebTcpipSendBin(hWeb0, "\hFFFB28", 3);    // ·û(
WebTcpipRecvExact(hWeb0, NULL, 7);
WebTcpipSendBin(hWeb0, 
  "\hFFFA28020749424D2D333237382D342D"
    // ·ú(··IBM-3278-4- 
  "\h45FFF0", 19);                        // E·ð              
WebTcpipRecvExact(hWeb0, NULL, 28);
WebTcpipSendBin(hWeb0, "\hFFFA2803070004FFF0", 9);
  // ·ú(·····ð
WebTcpipRecvExact(hWeb0, NULL, 9);
WebTcpipRecvExact(hWeb0, NULL, 347);

これは、前のセクションで紹介した Telnet セッションの最初の部分と似ています。これは、TN3270e プロトコルが Telnet プロトコルをベースにしているためです。ここれでも、変更する必要はありません。これはステートフルな接続志向プロトコルであるため、セッション処理は問題になりません。

セッションの最初の部分からのトラフィックを TELNET コードに解釈したものを次の表に示します。

サーバーからクライアント クライアントからサーバー
FF FD 28 (IAC DO TN3270E)
FF FB 28 (IAC WILL TN3270E)
FF FA 28 08 02 FF F0 (IAC SB TN3270E SEND DEVICE-TYPE IAC SE)
FF FA 28 02 07 49 42 4D 2D 33 32 37 38 2D 34 2D 45 FF F0 (IAC SB TN3270E DEVICE-TYPE REQUEST "IBM-3278-4-E" IAC SE)
FF FA 28 02 04 49 42 4D 2D 33 32 37 38 2D 34 2D 45 01 54 39 35 49 54 51 4D 55 FF F0 (IAC SB TN3270E DEVICE-TYPE IS "IBM-3278-4-E" CONNECT "T95ITQMU" IAC SE)
FF FA 28 03 07 00 04 FF F0 (IAC SB TN3270E FUNCTIONS REQUEST [BIND-IMAGE SYSREQ] IAC SE)
FF FA 28 03 04 00 04 FF F0 (IAC SB TN3270E FUNCTIONS IS [BIND-IMAGE SYSREQ] IAC SE)

簡単にまとめると、サーバーとクライアントは、プロトコル、デバイスの種類 (IBM-3278-4-E)、および、どのプロトコルの機能を使用するかどうかに同意します。ターミナル名 (T95ITQMU) は、クライアントではなく、サーバーによって割り当てられることにご注意ください。これは、サーバー システムがクライアント IP アドレスからターミナル名へのマッピング処理を行うデータベースを保持しているためです。

パート II:ユーザー操作

スクリプトの 2 番目の部分は、ユーザー操作が含まれます。次のリクエスト-レスポンス ペアの例は、ユーザーがアカウント番号 (238729) をテキスト フィールドに入力し、RETURN キーを打つやり取りを表します。

WebTcpipSendBin(hWeb0, 
  "\h00000000007DC6C61140C4F311C640F2"
     // ·····}ÆÆ·@Äó·Æ@ò  
  "\hF3F8F7F2F9FFEF", 23);               // óø÷òù·ï         
WebTcpipRecvExact(hWeb0, NULL, 199);

トラフィックが EBCDIC (ASCII ではなく) でエンコードされていることがわかり、アカウント番号は EBCDIC コード表を使用したリクエスト文字列見つけることができます: 238729 は、EBCDIC のバイナリ バイト シーケンス 0xF2 F3 F8 F7 F2 F9 として表されます。これはカスタマイズに関係する部分で、残りはそのまま残る可能性があります。

このメッセージのほかの部分の詳細は次のようになります。最初の 5 バイトは、TN3270e メッセージ ヘッダー (RFC 2355) を表します。

フィールド 長さ 例での値
データ型 1 バイト 0x00 3270-DATA
リクエスト フラグ 1 バイト 0x00 ERR-COND-CLEARED
レスポンス フラグ 1 バイト 0x00 NO-RESPONSE
シーケンス番号 2 バイト 0x0000 シーケンス番号は使用される場合と、そうでない場合があります。この場合は、使用されていません。

各クライアント リクエストは、2 バイト シーケンス (0xFF EF) で終了します。

リクエスト データの残りの部分 (この例では、#6 - #21 バイト) は、画面位置、キーコード、およびテキストを含むアプリケーション データです。

サーバー レスポンスは、記録セッションの対応するログ、または TrueLog ファイルで解析できます。この例では、レスポンスはリクエスト データと同様に、5 つの 0 バイト (0x00) で始まり、0xFF EF で終了する 199 バイトのデータ ブロックです。その間のデータの内容は、リクエスト データと同様に、カーソル位置、書式、およびテキスト (EBCDIC でエンコード) です。

関数ライブラリを使用してこれらを抽出する簡単なスクリプトのカスタマイズは、次のようになります。

ResetRequestData();
AppendRequestData("\h00000000007DC6C61140C4F311C640",
                15);
AppendRequestData(ASC2EBCDIC(sAccountNr) + "\hFFEF");    
SendTcpipRequest(hWeb0);
WebTcpipRecvUntil(hWeb, sResp, sizeof(sResp), nRecv,
                  "\hFFEF", 2);

ここで、文字列変数 sAccountNr は、アカウント番号 (238729 が記録中にしようされました) に対して導入されました。ASCII と EBCDIC 間での変換を行う関数 ASC2EBCDIC は、つぎのセクションで説明します。

最後に、柔軟性の無い WebTcpipRecvExactWebTcpipRecvUntil で置き換えられました。 終了バイト シーケンスが不明なため、ここでは適切な置換です。レスポンス データは、文字列変数 sResp に格納され、受信したバイト数は nRecv に保持されます。

ログおよび検証目的で、サーバー レスポンスは EBCDIC から ASCII に変換されます。例:

Writeln("Response: " + EBCDIC2ASC(sResp, nRecv));

必要に応じて、単一のレスポンス データ (続くリクエストのための入力として必要な新しい ID など) を、StrSearchDelimited 関数を使用してこのレスポンスから抽出することができます。

さらにカスタマイズ ステップを進めると、上記スクリプトの WebTcpipRecvUntil 呼び出しを、次のサーバー レスポンスで必要なすべてのアクションをカプセル化する MyWebTcpipRecv 関数で置き換えることが推奨されます。

  • 適切な終了バイト シーケンスで WebTcpipRecvUntil を呼び出す
  • レスポンスを EBCDIC から ASCII に変換する
  • レスポンスを出力ファイルに記録する (ASCII で)
  • 共通のエラー メッセージを検索して、レスポンスの汎用的なエラー チェックを行う
  • さらに検証やデータ抽出を行うために、レスポンス データを戻り値またはグローバル 変数として利用可能にする

Silk Performer スクリプトで、記録セッションの WebTcpipRecvExact 関数呼び出しを置換して、この新しい関数の呼び出しで各クライアント リクエストは続けられるべきです。