ヘルパクラス(参照コンテナ)C++のコンテナは基本的に値を格納するようにできている。オブジェクトのコピーは難しいところがあるので、ごく簡単に、参照を所有するコンテナを作る。非同期ソケットでは、connect()がすぐに返ってきてしまう。サーバがIPv4対応かIPv6対応か分からない状況では、ソケットを2本使う必要がある。両方でconnectを試みて、接続できたほうを生かす。接続できたかどうか判明したら、そのソケットは書き込み可能になる。接続できたら、こんどは先方からデータが届いたときに読み込み可能になる。gtk+では、g_io_add_watch_full()で、ソケットが読み込み可能、書き込み可能になったときにコールバックされる関数を登録できる。いうことを踏まえて、ソケットクラスを作る。ソケット一つにつきこのクラスのインスタンスを一つ用意する。後述するConnectionオブジェクトがSocketConnectionインスタンスを所有する。sockaddr_inはIPv4専用。sockaddr_in6はIPv6専用。格納できるほど大きい。<sys/socket.h>で定義。}コールバック関数を登録するメソッドを用意する。gtk+はこういうところが多くて面倒。ドキュメントも不足している。似たようなメソッドを作る。};状態機械IPv4/IPv6の両方に対応するために、サーバへの接続は、次のような手順を踏む。IPv4ソケット、IPv6ソケットでサーバへ接続するようconnect()する。どちらかが接続できれば、それ以外のソケットをすべて閉じる。すべてのソケットがエラーになれば終了。接続できたソケットで先方と通信する。そんな感じになるよう、サーバに接続するクラスを書いてみる。SocketConnectionオブジェクトを扱うメソッド。0が初期状態、1が(複数のソケットが)接続待ち、2が接続できて通信中。コールバックの条件を変更する。サーバにデータを送信。}set_state_2()のなかでサーバにデータを送信するコードを書いているあたり、やっつけ感が高い。真のリスナを登録させたりするのがいいだろうと思う。ウィンドウに表示するためのコールバック関数。}次は、ソケットのコールバック関数。ここでもサーバから受信するコードを直接書いている。error_dialog("接続に失敗しました。接続できたソケット以外閉じる。}ここでは非同期でやっているが、GUIプログラムの場合は、同期型(ブロッキングモード)でも同じようなコードになるだろう。ブロッキングモードのときは、read()でブロックしないように注意が必要。read()は次のいずれかで返る。non-blockingモードでも同じ。書き込み側でソケットが閉じられたバッファのバイト長より読めた長さが短くても、ソケットが閉じられたとは限らない。同様にread()の戻り値がバッファのバイト長と同じでも,まだデータがあるとは限らない。read()の戻り値がたまたまバッファのバイト長と同じで、まだデータがあると思ってさらにread()するとブロックしてしまう。一回だけread()したら読み込みのルーチンを終了し,メインループに戻すようにする。メインループのselect()でデータがあるかどうかを検査し、また読み込みルーチンを呼び出してもらう。non-blockingモードの設定、サーバへの接続ソケットを非同期にするにはfcntl()を使う。F_GETFLコマンドで現在のフラグを読み出し、F_SETFLで設定する。ブロックされず、EINPROGRESSエラーを発生させる。接続に成功すると書き込み可能状態になるので,そのようにコールバック関数を登録する。上記、set_state()のなかにコードがある。これでエラーが返れば接続に失敗している。接続に成功したら,読み込み可能状態でコールバックしてもらうように登録し直す。あとはコールバックされたらread()すればよい。error_dialog("ホストまたはポートが不正です。}あとは、開始ボタンのハンドラ。