12,964
回編集
419行目: | 419行目: | ||
== libSSH2ライブラリを使用したコマンドの使用例 == | == libSSH2ライブラリを使用したコマンドの使用例 == | ||
==== ブロッキングモード ==== | |||
以下の例では、リモート側のPCにSSH接続して、lsコマンドを実行してその結果をローカル側のPCに表示している。<br> | 以下の例では、リモート側のPCにSSH接続して、lsコマンドを実行してその結果をローカル側のPCに表示している。<br> | ||
<br> | <br> | ||
以下の例は、<u>ブロッキングモード</u>でlsコマンドを実行している。<br> | 以下の例は、<u>ブロッキングモード</u>でlsコマンドを実行している。<br> | ||
<br> | <br> | ||
<syntaxhighlight lang="make"> | <syntaxhighlight lang="make"> | ||
595行目: | 591行目: | ||
// チャンネルの終了を確認 | // チャンネルの終了を確認 | ||
// 終了コードおよび終了シグナルを取得して表示 | |||
int exitcode = 127; | int exitcode = 127; | ||
char *exitsignal = nullptr; | char *exitsignal = nullptr; | ||
630行目: | 627行目: | ||
#endif // DIVIDEBYZEROEXCEPTION_H | #endif // DIVIDEBYZEROEXCEPTION_H | ||
</syntaxhighlight> | |||
<br> | |||
==== ノンブロッキングモード ==== | |||
以下の例では、リモート側のPCにSSH接続して、lsコマンドを実行してその結果をローカル側のPCに表示している。<br> | |||
<br> | |||
以下の例は、<u>ノンブロッキングモード</u>でlsコマンドを実行している。<br> | |||
<u>ノンブロッキングモード</u> (シグナル / スロット) で設計する場合、libSSH2ライブラリの関数呼び出しは即座に返されて、処理がバックグラウンドで非同期に進行する。<br> | |||
これにより、プログラムは他の処理を続行でき、必要に応じてリモートホストとの通信が完了するのを待つことができる。<br> | |||
<br> | |||
ノンブロッキングモードを使用する場合、特に入出力操作が発生する待ち時間を最小限に抑え、プログラムがより効率的に動作することが期待される。<br> | |||
しかし、ノンブロッキングモードを扱う際には、非同期処理やイベント駆動型のプログラミングに慣れる必要がある。<br> | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
// SSHClient.hファイル | |||
#include <QCoreApplication> | |||
#include <QTcpSocket> | |||
#include <QTimer> | |||
#include <QDebug> | |||
#include <libssh2.h> | |||
class SSHClient : public QObject | |||
{ | |||
Q_OBJECT | |||
private: | |||
QTcpSocket *m_Socket; | |||
LIBSSH2_SESSION *m_Session; | |||
LIBSSH2_CHANNEL *m_Channel; | |||
QString m_Host; | |||
quint16 m_Port; | |||
QString m_User; | |||
QString m_Passwaord; | |||
public: | |||
SSHClient(QObject *parent = nullptr); | |||
~SSHClient(); | |||
void connectToHost(); | |||
private slots: | |||
void onConnected(); | |||
void authenticateUser(); | |||
void openChannel(); | |||
void executeCommand(); | |||
void onReadyRead(); | |||
void readOutput(); | |||
void closeChannel(); | |||
}; | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
// SSHClient.cppファイル | |||
#include "SSHClient.h" | |||
SSHClient::SSHClient(QObject *parent = nullptr) : QObject(parent), session(nullptr), channel(nullptr) | |||
{ | |||
m_Socket = new QTcpSocket(this); | |||
connect(m_Socket, &QTcpSocket::connected, this, &SSHClient::onConnected); | |||
connect(m_Socket, &QTcpSocket::readyRead, this, &SSHClient::onReadyRead); | |||
// libSSH2ライブラリの初期化 | |||
if (libssh2_init(0) != 0) { | |||
qDebug() << "libSSH2ライブラリの初期化に失敗"; | |||
return; | |||
} | |||
} | |||
SSHClient::~SSHClient() | |||
{ | |||
if (m_Channel) libssh2_channel_free(m_Channel); | |||
if (m_Session) { | |||
libssh2_session_disconnect(m_Session, "Normal Shutdown"); | |||
libssh2_session_free(m_Session); | |||
} | |||
libssh2_exit(); | |||
} | |||
void SSHClient::connectToHost() | |||
{ | |||
m_Socket->connectToHost(m_Host, m_Port); | |||
} | |||
void SSHClient::onConnected() | |||
{ | |||
qDebug() << "ホストへの接続に成功"; | |||
m_Session = libssh2_session_init(); | |||
libssh2_session_set_blocking(m_Session, 0); | |||
int rc = 0; | |||
do { | |||
rc = libssh2_session_handshake(m_Sssion, m_Socket->socketDescriptor()); | |||
} while (rc == LIBSSH2_ERROR_EAGAIN); | |||
if (rc) { | |||
qDebug() << "SSHのセッションの確立に失敗:" << rc; | |||
return; | |||
} | |||
authenticateUser(); | |||
} | |||
void SSHClient::authenticateUser() | |||
{ | |||
int rc = 0; | |||
do { | |||
// パスワード認証を行う場合 | |||
rc = libssh2_userauth_password(m_Session, m_User, m_Password); | |||
} while (rc == LIBSSH2_ERROR_EAGAIN); | |||
if (rc) { | |||
qDebug() << "認証に失敗:" << rc; | |||
return; | |||
} | |||
openChannel(); | |||
} | |||
void SSHClient::openChannel() | |||
{ | |||
int rc = 0; | |||
do { | |||
m_Channel = libssh2_channel_open_session(m_Session); | |||
} while (m_Channel == nullptr && libssh2_session_last_error(m_Session, nullptr, nullptr, 0) == LIBSSH2_ERROR_EAGAIN); | |||
if (!m_Channel) { | |||
qDebug() << "チャンネルのオープンに失敗"; | |||
return; | |||
} | |||
executeCommand(); | |||
} | |||
void SSHClient::executeCommand() | |||
{ | |||
int rc = 0; | |||
do { | |||
rc = libssh2_channel_exec(m_Channel, "ls -la"); | |||
} while (rc == LIBSSH2_ERROR_EAGAIN); | |||
if (rc) { | |||
qDebug() << "lsコマンドの実行に失敗:" << rc; | |||
return; | |||
} | |||
// lsコマンドの出力結果を取得を開始 | |||
QTimer::singleShot(0, this, &SSHClient::readOutput); | |||
} | |||
void SSHClient::onReadyRead() | |||
{ | |||
readOutput(); | |||
} | |||
void SSHClient::readOutput() | |||
{ | |||
if (!m_Channel) return; | |||
QByteArray buffer; | |||
buffer.resize(1024); | |||
int rc = 0; | |||
while (rc != LIBSSH2_ERROR_EAGAIN) { | |||
rc = libssh2_channel_read(m_Channel, buffer.data(), buffer.size()); | |||
if (rc > 0) { | |||
qDebug().noquote() << QString::fromUtf8(buffer.constData(), rc); | |||
} | |||
else if (rc < 0) { | |||
qDebug() << "チャンネルの読み取りエラー:" << rc; | |||
closeChannel(); | |||
return; | |||
} | |||
} | |||
// チャンネルがEOFかどうかを確認 | |||
if (libssh2_channel_eof(m_Channel) == 1) { | |||
closeChannel(); | |||
} | |||
else { | |||
// 続きを読み込む | |||
QTimer::singleShot(0, this, &SSHClient::readOutput); | |||
} | |||
} | |||
void SSHClient::closeChannel() | |||
{ | |||
if (!m_Channel) return; | |||
int rc = 0; | |||
do { | |||
rc = libssh2_channel_close(m_Channel); | |||
} while (rc == LIBSSH2_ERROR_EAGAIN); | |||
if (rc == 0) { | |||
int exitcode = libssh2_channel_get_exit_status(m_Channel); | |||
char *exitsignal = nullptr; | |||
libssh2_channel_get_exit_signal(m_Channel, &exitsignal, nullptr, nullptr, nullptr, nullptr, nullptr); | |||
if (exitsignal) { | |||
qDebug() << "Exit signal:" << exitsignal; | |||
} | |||
else { | |||
qDebug() << "Exit code:" << exitcode; | |||
} | |||
} | |||
libssh2_channel_free(m_Channel); | |||
m_Channel = nullptr; | |||
// Disconnect from the host | |||
m_Socket->disconnectFromHost(); | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
// main.cppファイル | |||
int main(int argc, char *argv[]) | |||
{ | |||
QCoreApplication a(argc, argv); | |||
SSHClient client; | |||
client.connectToHost("<リモートPC側のIPアドレスまたはホスト名>", <リモートPCのポート番号>, | |||
"<リモートPC側のユーザ名>", "<リモートPC側のユーザパスワード>"); | |||
return a.exec(); | |||
} | |||
</syntaxhighlight> | </syntaxhighlight> | ||
<br><br> | <br><br> |