VB クライアント から Linux サーバー への telnet ログインするには?

解決


Take  2005-05-23 12:08:12  No: 89968

VBクライアント: [Win2000 SP4] + [VB 6.0]
Linux サーバー: [Redhat Enterprise Linux WS release 3]

はじめてお便りさせていただきます。
過去ログ等を参考に
VB から Linux へtelnet ログイン を作成しております。
どなたかお知恵を拝借願えませんでしょうか?

teraterm からの ログインは成功し、
teraterm.ini の TelLog=on で取得したログは下記の通りです。
> FF FB 18
> FF FD 03
> FF FB 03
> FF FD 01
> FF FB 1F
< FF FD 18
< FF FD 20
> FF FC 20
< FF FD 23
> FF FC 23
< FF FD 27
> FF FC 27
< FF FB 03
< FF FD 03
< FF FB 01
< FF FD 1F
> FF FA 1F 00 50 00 18 FF F0
< FF FA 18 01 FF F0
> FF FA 18 00 76 74 31 30 30 FF F0
< FF FD 01
> FF FC 01
< FF FB 05
> FF FE 05
< FF FD 21
> FF FC 21

ところが、VB プログラムから
winsock コントロールの DataArrival イベントで データを受信すると
下記のようなデータを受信するのですが、
なにか不備な点があるのでしょうか?

[telnet ネゴシエーションで最初に送信するデータ]
> FF FB 18
> FF FD 03
> FF FB 03
> FF FD 01
> FF FB 1F

[DataArrival 1回目 で受信するデータ]
< FF FD 18
< FF FD 20
< FF FD 23
< FF FD 27
⇒ 上記データが一回のイベントで送られてきます、、、
   これは 正しいのでしょうか?

[上記 Arraival に対応してデータを送信]
> FF FC 20
> FF FC 23
> FF FC 27

[DataArrival 2回目 で受信するデータ]
< FF FB 03
< FF FB 01
⇒ teraterm で送信されてくる FF FD 03 が送信されてきません。。。。

上記を最後にDataArrival イベントが起きない

どなたか ご協力のほど宜しく御願いいたします。


Take  2005-05-23 13:00:59  No: 89969

長くなってしまいましたので、
ソースを別途後追いにて、提示させていただきます。

↓↓↓↓ ソース1 ↓↓↓↓
Option Explicit

Private mStrCmd                 As String   '** 受信データバッファ
Private mIntErrorNumber         As Integer  '** エラー番号
Private mStrErrorDescription    As String   '** エラー内容
Private mIntErrorStatus         As Integer  '** エラーステータス
Private mStrLog                 As String   '** ログ文字列

Private Declare Sub Sleep Lib "kernel32" ( _
    ByVal dwMilliseconds As Long)

'***********************************************************
'** 「収集装置 時計調整」ボタン押下時処理
'***********************************************************
Private Sub BtnConnect_Click()
    Dim strRet          As String       '** リターン値

    '** カーソルを砂時計にする
    Screen.MousePointer = vbHourglass
    '** メニューフォームを待機状態にする
    Me.Enabled = False

    '** 収集装置に TCP 接続する
    Call Me.Connect("192.168.1.53", 23, strRet)

    '** カーソルを矢印にする
    Screen.MousePointer = vbDefault
    '** メニューフォームを通常状態にする
    Me.Enabled = True

End Sub

'***********************************************************
'** TCP 接続 用
'***********************************************************
Public Sub Connect(ByVal strServerName As String, _
                   ByVal intServerPort As Integer, _
                   ByRef strRetCode As String)
On Error GoTo ErrorHandler:

    With Me.tcpClient
        '** 2重接続を防止する
        If .State = sckConnecting Or .State = sckConnected Then Exit Sub
        .LocalPort = 0
        .RemoteHost = strServerName
        .RemotePort = intServerPort
        .Connect
    End With

    Exit Sub

ErrorHandler:
    Call ErrorReport(ERROR_TRAPPED, Err.Number, Err.Description)
End Sub

'***********************************************************
'** TCP 接続切断 用
'***********************************************************
Public Sub Disconnect()
    On Error GoTo ErrorHandler:

    With Me.tcpClient
        '** 2重切断を防止する
        If .State = sckClosed Then Exit Sub

        .Close
        Do
            DoEvents
            If mIntErrorStatus Then Exit Sub
        Loop Until .State = sckClosed
    End With
    Exit Sub

ErrorHandler:
    Call ErrorReport(ERROR_TRAPPED, Err.Number, Err.Description)
End Sub

'***********************************************************
'** エラー設定 用
'***********************************************************
Private Sub ErrorReport(ByVal intStatus As Integer, _
                        ByVal intNumber As Integer, _
                        ByVal strDescription As String)
    mIntErrorStatus = intStatus

    mIntErrorNumber = intNumber
    mStrErrorDescription = strDescription
    mStrLog = mStrLog & "? " _
                          & intNumber & " " _
                          & strDescription _
                          & vbCrLf
End Sub

'***********************************************************
'** エラー初期化 用
'***********************************************************
Private Sub ErrorReset()
    mIntErrorStatus = ERROR_NOT_DETECTED
    mIntErrorNumber = 0
    mStrErrorDescription = ""
End Sub

'***********************************************************
'** エラーステータス取得 用
'***********************************************************
Public Property Get ErrorStatus() As Integer
    ErrorStatus = mIntErrorStatus
End Property

'***********************************************************
'** エラー番号取得 用
'***********************************************************
Public Property Get ErrorNumber() As Integer
    ErrorNumber = mIntErrorNumber
End Property

'***********************************************************
'** エラー内容取得 用
'***********************************************************
Public Property Get ErrorDescription() As String
    ErrorDescription = mStrErrorDescription
End Property

'***********************************************************
'** ログ文字列取得 用
'***********************************************************
Public Property Get Log() As String
    Log = mStrLog
End Property

'***********************************************************
'** ログ文字列初期化 用
'***********************************************************
Private Sub LogClear()
    mStrLog = ""
End Sub

'***********************************************************
'** TCP 通信 接続完了 用
'***********************************************************
Private Sub tcpClient_Connect()
    Const ERROR_NUM As Long = 9000

    Dim strRes      As String
    Dim strRetCode  As String

    Call LogClear
    Call ErrorReset
    
    mBlnConnected = True

  '** Telnet ネゴシエーション 開始
    Call TelnetNego

End Sub

'***********************************************************
'** TCP 通信 データ受信開始 用
'***********************************************************
Private Sub tcpClient_DataArrival(ByVal bytesTotal As Long)
'イベント***サーバーからデータが送られてきた時に実行される

    Dim bytData()   As Byte
    Dim strData     As String

    '** 受信データの受け取り
    '** および 対応したデータの送信
    Call TelnetRecvData
End Sub


Take  2005-05-23 13:02:11  No: 89970

ソース2個目です

↓↓↓↓ ソース2 ↓↓↓↓
'***********************************************************
'** TCP 通信 エラー 用
'***********************************************************
Private Sub tcpClient_Error(ByVal Number As Integer, Description As String, _
                            ByVal Scode As Long, ByVal Source As String, _
                            ByVal HelpFile As String, ByVal HelpContext As Long, _
                            CancelDisplay As Boolean)
    CancelDisplay = True
    Call ErrorReport(ERROR_IVENT_ARRISEN, Number, Description)
End Sub

'*******************************************************************
'** TCP 通信 : Telent ネゴシエートコマンドを受信する
'** argCnt = -1 : 受信済のものすべてを読み込む
'** argCnt <>-1 : 指定バイトだけ読み込む
'*******************************************************************
Private Function TelnetGetData(ByRef argStr As String, ByVal argCnt As Long)
On Error Resume Next
    Dim bytTmp()    As Byte
    Dim intIndex    As Integer

    If argCnt = -1 Then
        Call Me.tcpClient.GetData(bytTmp, vbByte + vbArray)
    Else
        Call Me.tcpClient.GetData(bytTmp, vbByte + vbArray, argCnt)
    End If

    Call HexConvStr(bytTmp, argStr)

End Function

'***********************************************************
'** TCP 通信 : Telent ネゴシエートコマンドを送信する
'***********************************************************
Private Sub TelnetNego()
On Error GoTo ErrorHandler
    Dim bytNego(128)    As Byte
    Dim strNego         As String

    strNego = "FFFB18FFFD03FFFB03FFFD01FFFB1F" ' telnet ネゴシエートコマンド
    Call StrConvHex(strNego, bytNego)
    Call tcpClient.SendData(bytNego)

    Exit Sub
ErrorHandler:
    Call ErrorReport(ERROR_TRAPPED, Err.Number, Err.Description)
End Sub

'***********************************************************
'** TCP 通信 : Telent ネゴシエートコマンドを1個ずつ読む
'***********************************************************
Private Function TelnetReadCmd() As String
On Error GoTo ErrorHandler
    Dim bytTmp(2)   As Byte
    Dim intRc       As Integer
    Dim strCmd      As String
    Dim strTmp      As String
    Dim intIndex    As Integer

    TelnetReadCmd = ""
    mStrCmd = ""
    While Len(mStrCmd) < 6    '** mStrCmd はグローバル変数
        intRc = TelnetGetData(strTmp, 3) '** 16進モード
        If intRc <> 0 Then
            Exit Function
        End If
        If Len(strTmp) <= 0 Then
            Exit Function
        End If
        mStrCmd = mStrCmd & strTmp
    Wend
    strTmp = Mid(mStrCmd, 1, 4)
    If strTmp = "FFFB" Or strTmp = "FFFD" Or strTmp = "FFFE" Then ' FFxxxx
        TelnetReadCmd = Mid(mStrCmd, 1, 6)
        Exit Function
    End If
    If strTmp = "FFFA" Then  ' SB 可変長。SE(FFF0) までがコマンド
        While InStr(mStrCmd, "FFF0") <= 0
            intRc = TelnetGetData(strTmp, -1) ' 16進モード
            If intRc <> 0 Then
                Exit Function
            End If
            mStrCmd = mStrCmd & CStr(bytTmp)
        Wend
        intIndex = InStr(mStrCmd, "FFF0")
        TelnetReadCmd = Mid(mStrCmd, 1, intIndex + 3)
        mStrCmd = Mid(mStrCmd, intIndex + 4)
    End If

    Exit Function

ErrorHandler:
    Call ErrorReport(ERROR_TRAPPED, Err.Number, Err.Description)
End Function

'***********************************************************
'** TCP 通信 :
'** Telent ネゴシエートコマンドを1個ずつ読む
'** および、対応した データを送信する
'***********************************************************
Private Sub TelnetRecvData()
On Error GoTo ErrorHandler
    Dim strCmd      As String
    Dim strTmp      As String
    Dim bytCmd(128) As Byte

    Do While 1  ' telnet ネゴシエート開始
        strCmd = TelnetReadCmd()  ' 16進モードでコマンドを受信
        Select Case strCmd
            Case "FFFD20", "FFFD23", "FFFD27", "FFFD24", "FFFE23", "FFFE27", "FFFE24", "FFFD01", "FFFD21"
                Call StrConvHex("FFFC" & Mid(strCmd, 5), bytCmd)
                Call tcpClient.SendData(bytCmd)
            Case "FFFB01"
                Call StrConvHex("FFFC" & Mid(strCmd, 5), bytCmd)
                Call tcpClient.SendData(bytCmd)
            Case "FFFB03"
                Call StrConvHex("FFFC" & Mid(strCmd, 5), bytCmd)
                Call tcpClient.SendData(bytCmd)
            Case "FFFB05"
                Call StrConvHex("FFFE" & Mid(strCmd, 5), bytCmd)
                Call tcpClient.SendData(bytCmd)
            Case "FFFD1F"  ' IAC SB Window
                Call StrConvHex("FFFA1F00500018FFF0", bytCmd)
                Call tcpClient.SendData(bytCmd)   ' window size  80x24
                'Call StrConvHex("FFFA1F00840020FFF0", bytCmd)
                'Call tcpClient.SendData(bytCmd)   ' window size  132x32
            Case "FFFA18"  ' IAC SB Terminal-Type
                Call StrConvHex("FFFA18007674313030FFF0", bytCmd)
                Call tcpClient.SendData(bytCmd)   ' IAC SB Terminal-Type vt100
            Case ""  ' コマンド終了
                Exit Do
        End Select
    Loop

    Exit Sub

ErrorHandler:
    Call ErrorReport(ERROR_TRAPPED, Err.Number, Err.Description)
End Sub

'***********************************************************
'** TCP 通信 用 Hex => 文字列 変換
'***********************************************************
Private Sub HexConvStr(ByRef argByt() As Byte, ByRef argStr As String)
    Dim strTmp      As String
    Dim intIndex    As Integer

    intIndex = 0
    While intIndex <= UBound(argByt)
        If Len(Hex(argByt(intIndex))) < 2 Then
            strTmp = strTmp & "0" & Hex(argByt(intIndex))
        Else
            strTmp = strTmp & Hex(argByt(intIndex))
        End If
        intIndex = intIndex + 1
    Wend

    argStr = strTmp
End Sub

'***********************************************************
'** TCP 通信 用 文字列 => Hex 変換
'***********************************************************
Private Sub StrConvHex(ByVal argStr As String, ByRef argByt() As Byte)
    Dim strTmp      As String
    Dim intIndex    As Integer
    Dim intLen      As Integer
    Dim bytTmp      As Byte
    
    intIndex = 1
    intLen = 0
    While intIndex < Len(argStr)
        strTmp = Mid(argStr, intIndex, 2)
        bytTmp = CLng("&H" & strTmp)
        argByt(intLen) = bytTmp
        intLen = intLen + 1
        intIndex = intIndex + 2
    Wend
End Sub


Take  2005-05-23 14:01:04  No: 89971

>[DataArrival 2回目 で受信するデータ]
>< FF FB 03
>< FF FB 01
>⇒ teraterm で送信されてくる FF FD 03 が送信されてきません。。。。

>上記を最後にDataArrival イベントが起きない
上記送信後の
winsock コンポーネントの State は 「7」です。
Err.Number は 「0」です。
ネゴシエートコマンドの受送信中に
winsock コンポーネント の Error イベントは発生しません。

TerminalType は 「VT100」 を使用したいのですが、
データの送信まで たどりつきません。

上記、何卒宜しく御願いいたします。


Take  2005-05-24 01:54:49  No: 89972

すいません
下記ソース転載漏れです。

'** TCP 関連 エラー定数
Public Const ERROR_NOT_DETECTED     As Integer = 0
Public Const ERROR_IVENT_ARRISEN    As Integer = 1
Public Const ERROR_TRAPPED          As Integer = 2


ガッ  2005-05-24 04:12:55  No: 89973

ノ<ソースが、めちゃくちゃ長すぎです(orz
  うーん…これはデバッグですね(@@;

一番最初の投稿に、
> [DataArrival 1回目 で受信するデータ]
> < FF FD 18
> < FF FD 20
> < FF FD 23
> < FF FD 27
> ⇒ 上記データが一回のイベントで送られてきます、、、
>    これは 正しいのでしょうか?
と書いています。
TCPではご承知の通り一回の受信で複数のデータが断片的に届きます。
なので、受信側にループを設けている部分になんらかの「欠陥」があるかと(orz
あと、TelnetGetData()に戻り値が設定されていないような気がしますが?
他にも色々ありそうですが、デバッグすればいいかと思います。

※私はtelnet仕様を知りません。


Take  2005-05-24 05:05:11  No: 89974

ガッ さん  ご回答有難うございます。

>ノ<ソースが、めちゃくちゃ長すぎです(orz
申し訳ないです ^^;

またまた長文になってしまい申し訳ありませんが、、、、、

>TCPではご承知の通り一回の受信で複数のデータが断片的に届きます。
上記は、おっしゃるとおりです。

ただ、Teraterm での通信では
< FF FD 18
< FF FD 20
> FF FC 20
< FF FD 23
> FF FC 23
< FF FD 27
> FF FC 27
というように
対応するtelnet コマンドが交互に行きかっているように
見受けられます。

なので、
サーバー側では
< FF FD 18
< FF FD 20
を送った後、
対応した telnetコマンドがクライアントから送られてくるまで
待ちになるのかと思っていたのです。

<<私の思い描いていたネゴは>>
VB側では
1回目の DataArrivalイベントで
< FF FD 18
< FF FD 20
を受信して
> FF FC 20
をサーバーに送信

2回目の DataArrivalイベントで
< FF FD 23
を受信して
> FF FC 23
をサーバーに送信

3回目の DataArrivalイベントで
< FF FD 27
を受信して
> FF FC 27
をサーバーに送信

するものだと思っていました。。。。

<<実際には>>
VB側 の1回目の DataArrivalイベントで
< FF FD 18
< FF FD 20
< FF FD 23
< FF FD 27
が送られてきている(※)ので、
実際には「待ちにはならない」ようですが。。。。
  ※ デバッグ済
     DataArraival の 引数:bytesTotal=12
     かつ DataArrival イベント内で tcpClient.GetData をコールし
     クイックウォッチしてみましたが、
     < FF FD 18
     < FF FD 20
     < FF FD 23
     < FF FD 27
     を受信していました。

上記「待ちにはならない」が正しいかどうかの確認のため
質問させていただいた次第です。

>あと、TelnetGetData()に戻り値が設定されていないような気がしますが?
上記はおっしゃるとおりですね^^;
修正いたします。


Take  2005-05-24 06:15:09  No: 89975

わかりにくいので訂正いたします ^^;

>> ⇒ 上記データが一回のイベントで送られてきます、、、
>>    これは 正しいのでしょうか?
という質問は、
上記「待ちにはならない」が正しいかどうかの確認のため
質問させていただいた次第です。

それよりも問題は
>[DataArrival 2回目 で受信するデータ]
>< FF FB 03
>< FF FB 01
>⇒ teraterm で送信されてくる FF FD 03 が送信されてきません。。。。

>⇒ 上記受信を最後にDataArrival イベントが起きない
上記2点かと思っているのですが。。。。
誤りでしょうか?


猫葉  2005-05-24 08:00:00  No: 89976

以下は参考まで
> FF FB 18      IAC-WILL-TerminalType
> FF FD 03    IAC-DO-Reconnection
> FF FB 03    IAC-WILL-SUPPRESS_GO_AREAD
> FF FD 01    IAC-DO-ECHO
> FF FB 1F    IAC-WILL-WindowSize
< FF FD 18    IAC-DO-TerminalType
< FF FD 20    IAC-DO-TerminalSpeed
> FF FC 20    IAC-WON'T-TerminalSpeed
< FF FD 23    IAC-DO-XWindowDisplayLocation
> FF FC 23    IAC-WON'T-XWindowDisplayLocation
< FF FD 27    IAC-DO-NewEnvironment
> FF FC 27    IAC-WON'T-NewEnvironment
< FF FB 03    IAC-WILL-SUPPRESS_GO_AREAD
< FF FD 03    IAC-DO-SUPPRESS_GO_AREAD
< FF FB 01    IAC-WILL-ECHO
< FF FD 1F    IAC-DO-WindowSize
> FF FA 1F 00 50 00 18 FF F0    IAC-SB-WindowSize(00 50 00 18)-IAC-SE (80*24) 
< FF FA 18 01 FF F0      IAC-SB-TerminalType-SEND-IAC-SE (ターミナルタイプ送信要求)
> FF FA 18 00 76 74 31 30 30 FF F0  IAC-SB-TerminalType-IS-VT100-IAC-SE (VT100)
< FF FD 01    IAC-DO-ECHO
> FF FC 01    IAC-WON'T-ECHO
< FF FB 05    IAC-WILL-Status
> FF FE 05    IAC-DON'T-Status
< FF FD 21    IAC-DO-RemoteFlowControl
> FF FC 21    IAC-WON'T-RemoteFlowControl


通りすがり  2005-05-24 09:09:02  No: 89977

始めに断って置きますが、
私もTelnetプロトコルに詳しい訳ではないです。
正確な点はRFC等で確認されることをお勧めします。

>> ⇒ 上記データが一回のイベントで送られてきます、、、
>>    これは 正しいのでしょうか?

正しいでしょう。
ガッさんも言われてますようにデータの区切りはなしで受信されるものですし、
TELNET上の相手からの要求は開始時にのみに決まった形で来るものと考えずに
各要求コマンドがどんなときにどんな順で来ても対応すべきでしょう。
(常に平文の中にコマンドが含まれると考えておく必要があります。)

>[DataArrival 2回目 で受信するデータ]
>< FF FB 03
>< FF FB 01
>⇒ teraterm で送信されてくる FF FD 03 が送信されてきません。。。。

応答があることを期待してはいけないでしょう。
(対応できないコマンドは無視するようなものもあるでしょうし、
 それまでのやり取りでコマンドは変わるのが普通ですが、
 同じである必要もないでしょうから。)
DO応答があったときのみ、そのオプションが使えると解釈すべきです。

VBというよりTELNETプロトコルの解釈に関する問題のように思えます。
ご存知だと思いますが、TELNETプロトコルでは
WILLコマンド(FF FB)が来たらDOコマンド(FF FD)又はDONT(FF FE)、
DOコマンドがきたらWILLコマンド(FF FB)又はWONT(FF FC)を返す
のが基本です。
(これやるよ:WILL → いいよ:DO   or ダメ:DONT)
  これをやって:DO → いいよ:WILL or ヤダ:WONT)
是正応答がなければ、やるべきでないしやっても相手次第です。

単にTELNETクライアントで人間が操作しているコマンド入力や
メッセージの確認程度を自動化させるようなものならば
要求コマンドは一切発行しないで、
向こうからの要求コマンドはすべてDONT又はWONTを返すだけで
十分でしょう。(いわゆるDUMB端末)


Take  2005-05-24 11:38:49  No: 89978

猫葉さま、通りすがりさま
ご回答、参考意見など ありがとうございます。

試行錯誤の上、どうにか ログインプロンプトの受信までこぎつけました。

足りなかったのは
< FF FD 18        IAC-DO-TerminalType
受信に対応したデータの送信のようです。
(Teratermのログにはありませんが・・^^;)

上記コマンドに
> FF FB 18        IAC-WILL-TerminalType
を送信することでログインまでサクサク進みました。^^

まだ別途問題がございますが、
こちらについては、別質問を立てさせていただき、
とりあえず、本件については解決としたいと思います。

ありがとうございました。

↓↓↓↓  修正した箇所を 関数ごとに転載します ↓↓↓↓
'*******************************************************************
'** TCP 通信 : Telent ネゴシエートコマンドを受信する
'** argCnt = -1 : 受信済のものすべてを読み込む
'** argCnt <>-1 : 指定バイトだけ読み込む
'*******************************************************************
Function TelnetGetData(ByRef argStr As String, ByVal argCnt As Long) As Integer
On Error GoTo ErrorHandler
    Dim bytTmp()    As Byte
    Dim intIndex    As Integer
    
    '** リターン正常を設定
    TelnetGetData = 0
    
    If argCnt = -1 Then
        Call Me.tcpClient.GetData(bytTmp, vbByte + vbArray)
    Else
        Call Me.tcpClient.GetData(bytTmp, vbByte + vbArray, argCnt)
    End If
    
    Call HexConvStr(bytTmp, argStr)

    Exit Function
ErrorHandler:
    Call ErrorReport(ERROR_TRAPPED, Err.Number, Err.Description)
    '** リターン異常を設定
    TelnetGetData = -1
    Exit Function
End Function

'***********************************************************
'** TCP 通信 : Telent ネゴシエートコマンドを1個ずつ読む
'***********************************************************
Private Function TelnetReadCmd() As String
On Error GoTo ErrorHandler
'    Dim bytTmp(128) As Byte
    Dim intRc       As Integer
    Dim strCmd      As String
    Dim strTmp      As String
    Dim intIndex    As Integer

    Dim bytUser(64) As Byte
    Dim bytPass(64) As Byte

    TelnetReadCmd = ""
    mStrCmd = ""
    While Len(mStrCmd) < 6    '** mStrCmd はグローバル変数
        intRc = TelnetGetData(strTmp, 3) '** 16進モード
        If intRc <> 0 Then
            Exit Function
        End If
        If Len(strTmp) <= 0 Then
            Exit Function
        End If
        mStrCmd = mStrCmd & strTmp
    Wend
    
    '** 受信データが Telnet コマンドの場合
    strTmp = Mid(mStrCmd, 1, 4)
    If strTmp = "FFFB" Or strTmp = "FFFD" Or strTmp = "FFFE" Then ' FFxxxx
        TelnetReadCmd = Mid(mStrCmd, 1, 6)
        Exit Function
    ElseIf strTmp = "FFFA" Then  ' SB 可変長。SE(FFF0) までがコマンド
        While InStr(mStrCmd, "FFF0") <= 0
            intRc = TelnetGetData(strTmp, 1) ' 16進モード
            If intRc <> 0 Then
                Exit Function
            End If
            mStrCmd = mStrCmd & strTmp
        Wend
        intIndex = InStr(mStrCmd, "FFF0")
        TelnetReadCmd = Mid(mStrCmd, 1, 6)
        mStrCmd = Mid(mStrCmd, intIndex + 4)
    '** 受信データが Telnet コマンド以外の場合
    Else
        intRc = TelnetGetData(strTmp, -1) ' 16進モード
        mStrCmd = mStrCmd & strTmp
        
        '** 「ログインユーザー入力プロンプト」が表示されたら
        If InStr(mStrCmd, "6C6F67696E3A") > 0 Then
            '** ログインユーザーを送信する
            bytUser(1) = CLng("&H72") '** 「r」
            bytUser(2) = CLng("&H6F") '** 「o」
            bytUser(3) = CLng("&H6F") '** 「o」
            bytUser(4) = CLng("&H74") '** 「t」
            bytUser(5) = CLng("&H0D") '** 「<CR>」
            Call tcpClient.SendData(bytUser)
        End If
    End If

    Exit Function

ErrorHandler:
    Call ErrorReport(ERROR_TRAPPED, Err.Number, Err.Description)
End Function

'***********************************************************
'** TCP 通信 :
'** Telent ネゴシエートコマンドを1個ずつ読む
'** および、対応した データを送信する
'***********************************************************
Private Sub TelnetRecvData()
On Error GoTo ErrorHandler
    Dim strCmd      As String
    Dim strTmp      As String
    Dim bytCmd(128) As Byte

    Do While 1  ' telnet ネゴシエート開始
        strCmd = TelnetReadCmd()  ' 16進モードでコマンドを受信
        Select Case strCmd
            Case "FFFD20", "FFFD23", "FFFD27", "FFFD24", "FFFE23", "FFFE27", "FFFE24", "FFFD01", "FFFD21"
                Call StrConvHex("FFFC" & Mid(strCmd, 5), bytCmd)
                Call tcpClient.SendData(bytCmd)
            Case "FFFD18", "FFFD03"
                Call StrConvHex("FFFB" & Mid(strCmd, 5), bytCmd)
                Call tcpClient.SendData(bytCmd)
            Case "FFFB01"
                Call StrConvHex("FFFD" & Mid(strCmd, 5), bytCmd)
                Call tcpClient.SendData(bytCmd)
            Case "FFFB03"
                Call StrConvHex("FFFD" & Mid(strCmd, 5), bytCmd)
                Call tcpClient.SendData(bytCmd)
            Case "FFFB05"
                Call StrConvHex("FFFE" & Mid(strCmd, 5), bytCmd)
                Call tcpClient.SendData(bytCmd)
            Case "FFFD1F"  ' IAC SB Window
                Call StrConvHex("FFFA1F00500018FFF0", bytCmd)
                Call tcpClient.SendData(bytCmd)   ' window size  80x24
                'Call StrConvHex("FFFA1F00840020FFF0", bytCmd)
                'Call tcpClient.SendData(bytCmd)   ' window size  132x32
            Case "FFFA18"  ' IAC SB Terminal-Type
                Call StrConvHex("FFFA18007674313030FFF0", bytCmd)
                Call tcpClient.SendData(bytCmd)   ' IAC SB Terminal-Type vt100
'            Case "FFFE01"  ' コマンド終了
'                Exit Do
            Case ""  ' コマンド終了
                Exit Do
            Case Else
                Call MsgBox("<" & strCmd, vbOKOnly + vbInformation, "RecvMes")
        End Select
    Loop

    Exit Sub

ErrorHandler:
    Call ErrorReport(ERROR_TRAPPED, Err.Number, Err.Description)
End Sub


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加