winsockを使ってみる。(2) -acceptスレッド-
前回(winsockを使ってみる。(1) - while( c++ );)、コネクションを作って簡単な送受信を行いましたが、acceptはいわゆるブロッキング関数であり、クライアントが接続してくるまで、またはサーバソケットが閉じられるまで、呼び出し元スレッドが停止します。このままでは複数のクライアントと通信する場合やサーバ側で何らかの処理を行う場合に不都合なので、サブスレッドでacceptを行います。
- メインスレッドからacceptスレッドを作成
- acceptスレッドでクライアントのconnect待ち
- とりあえずコネクション確立時に文字列を送り返す
- サーバソケットを閉じるとacceptスレッド終了
hogeテンプレートライブラリ
- smart_ptr
- shared_ptr
- weak_ptr
- intrusive_ptr
- scoped_ptr
- nullptr
- enable_shared_from_this
- thread
- thread
- event
Server
/** * acceptスレッド実行関数 */ struct AcceptThreadFunc { void operator()() { for( ; ; ) { //クライアントの接続待ち std::cout << "クライアントの接続待ち" << std::endl; SocketPtr client = socket->accept(); if( client == nullptr )break; //ソケットからストリームを取得 SocketStreamWeakPtr stream = client->get_stream(); //適当な文字列を送る stream->write_line( "hoge" ); } } AcceptThreadFunc( const ServerSocketPtr& socket ) : socket( socket ) {} ServerSocketPtr socket; };
#include <net/socket.h> #include <hoge/thread/thread.h> int main() { try { //winsock初期化 net::startup(); //指定ポートでサーバ用TCPソケットを作成 ServerSocketPtr socket = IServerSocket::create( 12345 ); //acceptスレッド開始 hoge::thread_ptr accept_thread = hoge::thread::create( AcceptThreadFunc( socket ) ); accept_thread->start(); for( ; ; ) { if( GetAsyncKeyState( VK_ESCAPE ) & 0x8000 )break; } //ソケットを閉じて、acceptスレッドを終了させる socket->close(); //acceptスレッドの終了待ち accept_thread->join(); } catch( net::socket_error& e ) { std::cout << e.what() << std::endl; } //winsock破棄 net::cleanup(); return 0; }
- ISocketにcloseメソッドを追加した。
- 例外発生時にacceptスレッドが正常終了しないですが、とりあえず気にしない。
- Escキーで終了。
Client
#include <net/socket.h> int main() { try { using namespace net::tcp; //winsock初期化 net::startup(); //クライアント用TCPソケットを作成 ClientSocketPtr socket = IClientSocket::create(); //指定ポート、IPアドレスのサーバに接続 socket->connect( 12345, "localhost" ); //ソケットからストリームを取得 SocketStreamWeakPtr stream = socket->get_stream(); //1行分の文字列を受信 std::string str; stream->read_line( str ); std::cout << str; } catch( net::socket_error& e ) { std::cout << e.what() << std::endl; } net::cleanup(); return 0; }
サンプル
- winsock_02.zip
- VC++2008EEで動作確認