Entering Passive Mode

カテゴリ 'C++, C' の記事
< 1 2 3 4 5 6 >

仮開通

いよいよ今年も最後になった。今日中に開通できるか。

PASV コマンドを引き金として、UPnPNT で登録する。
前作ったループの中身を書き換えてみよう。
TcpConsole も使って行単位の送受信を行う。

    TcpConsole *client, *server;
    bool pasvReceived = false;

ループの中身はこんな感じに変更。

C++ からの UPnP Nat Traversal の利用

今日はもう一つの壁 UPnPNT を C++ で実装する。
面倒なので、関数化しておく。今のところ汎用じゃないけど。

void RegisterPortMapping(const sockaddr_in &localAddr, sockaddr_in *externalAddr) {

    // 内部ホストの文字列 IP と、自然表現のポート番号を得る。
    char *localIP = inet_ntoa(localAddr.sin_addr);
    u_short localPort = ntohs(localAddr.sin_port);

    // COM の初期化
    CoInitialize(NULL);

行指向

そろそろメインの UPnPNT の実装をしたい所だが、
その前にまだまだ壁がある。今日はひとつの壁を取っ払おう。

FTP は行志向のプロトコルだ。コントロール接続においては、
クライアント・サーバともに行単位でデータをやり取りする。
コマンド行や応答行は、原則として CRLF で終端するので、
データを行単位で送受信できると効率が良い。

残念ながら、ソケットを使った TCP のプログラミングでは、
一度の send が、一度の recv で受け取られる保障はない。
TCP により送信される順番と到達は保障されるが、
それがどのように分割されるかは分からない。

とりあえず動作

今日はプロキシとしての実装を行う。
クライアントから接続があった場合、
代行してサーバに接続する。

    auto_ptr<Socket> client(listener->Accept());

    sockaddr_in sa;
    memset(&addr, 0, sizeof(sockaddr_in));
    sa.sin_family = AF_INET;
    sa.sin_port = htons(21);
    sa.sin_addr.s_addr = inet_addr("192.168.0.77");

FTP プロキシの実装

やっと実装に入れる。

ネットワークプログラミングなので、
同じコンピュータでテストしても面白くない。
そこでプロキシ用にコンピュータを用意した。

まず必要なのが、クライアントの通信を待機するソケット。
ポートは 2121 にしよう。なお、IP は、192.168.0.111 だ。

sockaddr_in を準備。ここは普通の C コード
(クラス化してもいいんだけど……構想中。)

Socket クラス

そして、ソケットのクラス。

class Socket {
public:
    enum TransmissionDirection {
        Incoming = 0x1,
        Outgoing = 0x2,
        Both     = Incoming | Outgoing
    };

    Socket(int family, int type, int protocol);
    explicit Socket(SOCKET socket);

外堀実装の続き

前回もそうだけど、デストラクタなどメンバは一部省略。

// イベント
class Event : public WaitableHandle {
public:
    Event(bool manualReset, bool initiallyActive) throw(WindowsException);
    virtual void Activate(void) throw(WindowsException);
    virtual void Inactivate(void) throw(WindowsException);
    virtual void Pulse(void) throw(WindowsException);
};

実装開始

いよいよ FTP サーバの実装に入る
プログラミング環境は色々と迷ったが、
オーソドックスに C/C++ にすることにした。

すぐにでもソケットの処理に入ってもいいが、
ここは趣味。最大限悪い癖を発揮して、
意味も無く外堀のクラス化を進めていこう。

ソケットを扱うサーバプログラミングの場合、
マルチスレッドになることが多い。
Thread 周りのクラスを作成しよう。

NAT Traversal はどうする

FTP サーバの構築は、ソケット部のプログラムだけなので楽だ。
問題になりそうなのは、NAT Traversal の実装。
UPnP の仕様を確認して実装するのは大変そうだ。
何か楽できないだろうか。調べてみた。

Windows XP 以降には、ICS/ICF という技術基盤がある。
一部として Network Address Translation Traversal があり、
API が公開されていることが分かった。

MSDN ライブラリで調べてみたが、どうやら C API ではなく、
インタフェースベースの API のようだ。
IUPnPNAT が親玉っぽいが、取得方法が分からない。

内容の整理

処理の流れを整理してみよう

大文字はグローバル、小文字はプライベート IP/Port
R: リモートホスト(クライアント)
P: FTP プロキシ IP/Port
S: FTP サーバ IP/Port
D: データ接続用 IP/Port
静: 静的 NAPT ルール
動: 動的 NAPT ルール

< 1 2 3 4 5 6 >
このページのトップへ戻る
© 2008 Project Loafer/Project Fireball and all blog writers. Powered by Nucleus CMS