FC2ブログ

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

POCO を使って簡単な TCP Server アプリケーションを作る

研究目的などでネットワーク通信を行う必要があると,TCP とテキストで簡単に実装してしまう,ということがよくあります.Java や Python ならば標準ライブラリが充実しているので非常に楽ですが,C/C++ には標準のソケット通信ライブラリがありません.POCO は C++ 用の便利なコンポーネントライブラリで,ネットワークやファイルIOなど様々な機能を提供してくれます.本記事では POCO による TCP Server の作成方法を説明します.

Keywords: POCO, TCP, Server


作業環境
Windows7 Professional 64bit
Visual C++ 2008 Express

本記事で利用する POCO のコンポーネントを以下に列挙します.

 Poco::Net::ServerSocket
 Poco::Net::StreamSocket
 Poco::Net::TCPServer
 Poco::Net::TCPServerConnection
 Poco::Net::TCPServerConnectionFactory

下の2つは利用者が実装する abstract class です.

1.TCPServerConnection の実装

run() メソッドを継承し,クライアントとのやり取りについて記述します.run() メソッドを抜けると TCPServerConnection インスタンスは自動的に破棄されて,接続が自動的に閉じられます.run() メソッド内では socket() メソッドを通じてソケットにアクセスし,データの送受信ができます.

class MyConnection : public TCPServerConnection {
public:
MyConnection(const StreamSocket &socket) : TCPServerConnection(socket)
{
}

virtual ~MyConnection()
{
}

virtual void run()
{
static const char message[] = "This is TCP server sample\n";
socket().sendBytes(message, sizeof(message) - 1);
}
};


2.TCPServerConnectionFactory の実装

createConnection(const StreamSocket&) メソッドを継承します.このメソッドは Factory Method パターンで,TCPServerConnection インスタンスを返すのが仕事です.

class MyConnectionFactory : public TCPServerConnectionFactory {
public:
MyConnectionFactory()
{
}

virtual ~MyConnectionFactory()
{
}

virtual TCPServerConnection* createConnection(const StreamSocket &socket)
{
return new MyConnection(socket);
}
};


3.main.cpp

TCPServer クラスをインスタンス化し,待機状態に入ります.注意点として,TCPServer::start() を呼び出す前に,ServerSocket をリスニング状態にする(listen メソッドを呼ぶ)のを忘れないでください.

int main(int, char**) {
static const Poco::UInt16 SERVER_PORT = 8888;

ServerSocket sock(SERVER_PORT);
sock.listen();

TCPServer server(new MyConnectionFactory(), sock);

printf("Simple TCP Server Application.\n");
printf("command:\n");
printf(" q | quit : Quit application.\n");
printf("\n");

server.start();

bool running = true;
while(running) {
char buff[256];

if(fgets(buff, sizeof(buff), stdin) == NULL) {
running = false;
} else {
buff[strlen(buff) - 1] = '\0';

if(strcmp(buff, "quit") == 0 ||
strcmp(buff, "q") == 0)
{
printf(">> QUIT command accepted.\n");
running = false;
} else {
printf(">> UNKNOWN command.\n");
}
}
}

server.stop();

return 0;
}


4.最後に

私は以前 TCP を書くときには boost の Asio を使っていました.こちらも非常に優れたライブラリ(私にはほとんど魔法)ですが,内部の依存関係が把握できないため,他人にソースを渡すときに膨大なヘッダ群を同梱することになります.これは非常に嫌がられます.その点で POCO はポータビリティが高く,今回のケースでは Foundation と Net だけ同梱すれば,ソースを貰った人はすぐにビルドできます.これはとても気持ちいいことだと思いませんか?

付録 main.cpp
#include <stdio.h>
#include <stdlib.h>

#include <Poco/Net/ServerSocket.h>
#include <Poco/Net/StreamSocket.h>
#include <Poco/Net/TCPServer.h>
#include <Poco/Net/TCPServerConnection.h>
#include <Poco/Net/TCPServerConnectionFactory.h>


using Poco::Net::ServerSocket;
using Poco::Net::StreamSocket;
using Poco::Net::TCPServer;
using Poco::Net::TCPServerConnection;
using Poco::Net::TCPServerConnectionFactory;


class MyConnection : public TCPServerConnection {
public:
MyConnection(const StreamSocket &socket) : TCPServerConnection(socket)
{
}

virtual ~MyConnection()
{
}

virtual void run()
{
static const char message[] = "This is TCP server sample\n";
socket().sendBytes(message, sizeof(message) - 1);
}
};


class MyConnectionFactory : public TCPServerConnectionFactory {
public:
MyConnectionFactory()
{
}

virtual ~MyConnectionFactory()
{
}

virtual TCPServerConnection* createConnection(const StreamSocket &socket)
{
return new MyConnection(socket);
}
};


int main(int, char**) {
static const Poco::UInt16 SERVER_PORT = 8888;

ServerSocket sock(SERVER_PORT);
sock.listen();

TCPServer server(new MyConnectionFactory(), sock);

printf("Simple TCP Server Application.\n");
printf("command:\n");
printf(" q | quit : Quit application.\n");
printf("\n");

server.start();

bool running = true;
while(running) {
char buff[256];

if(fgets(buff, sizeof(buff), stdin) == NULL) {
running = false;
} else {
buff[strlen(buff) - 1] = '\0';

if(strcmp(buff, "quit") == 0 ||
strcmp(buff, "q") == 0)
{
printf(">> QUIT command accepted.\n");
running = false;
} else {
printf(">> UNKNOWN command.\n");
}
}
}

server.stop();

return 0;
}

スポンサーサイト

テーマ : プログラミング
ジャンル : コンピュータ

コメントの投稿

非公開コメント

プロフィール

Ishida Akihiko

Author:Ishida Akihiko
FC2ブログへようこそ!

免責事項
当サイトに掲載する記事内容は,必ずしも正確性,信頼性,妥当性,有用性,完成度などを保証しません.記事の利用はすべて自己責任でお願いします.当サイトに掲載された内容によって発生したいかなる損害に対しても,管理人は一切の責任を負いかねます.
最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
アクセスカウンター
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QR
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。