FC2ブログ

チャットサーバのsocket

チャットのシステムはsocketで接続していますので、チャットサーバは多くのチャットクライアントからの接続を待ち受けるサーバ型のsocketとして動作しないといけないです。
これをC言語で作成しているのですが、その方法について記述します。
(ある種備忘録的なものです)

サーバ型のsocketの作成方法は

  1. socket()関数でPF_INET, SOCK_STREAM, IPPROTO_TCPを指定して待ち受け用のsocketハンドルを作成する。

  2. fcntl()関数でF_SETFL, O_NONBLOCKを指定して、そのsocketハンドルをブロッキングしないモードにする。

  3. struct sockaddr_in bind_addressの構造体に、待ち受けのポート番号を指定して、bind()関数を呼び出し、待ち受けの指定をする。

  4. listen()関数を呼び出し、待ち受けを開始する。


という順番ですね。
以下で使っているsetsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &trueval, sizeof(trueval)は
前回システム終了時から再起動の間隔が短くて、待ち受けのポートがまだ開いてない場合でも
そのポートを再利用できるようにするというおまじないです。
これらをまとめるとソースは以下のような感じになります。


int fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (fd == -1) {
printerror("socket %s", strerror(errno));
exit(1);
}

struct sockaddr_in bind_address;
memset(&bind_address, 0, sizeof(bind_address));
bind_address.sin_family = AF_INET;
bind_address.sin_addr.s_addr = INADDR_ANY;
bind_address.sin_port = htons(port);
if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) {
printerror("O_NONBLOCK %s", strerror(errno));
exit(1);
}
int trueval = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &trueval, sizeof(trueval)) == -1) {
printerror("setsockopt SO_REUSEADDR %s", strerror(errno));
exit(1);
}
if (bind(fd, (struct sockaddr *) &bind_address, sizeof(bind_address)) == -1) {
printerror("bind %s", strerror(errno));
exit(1);
}
if (listen(fd, backlog) == -1) {
printerror("bind %s", strerror(errno));
exit(1);
}


この後に、実際に待ち受けのsocketに接続が行われたときの処理を行うのですが、
その処理は、すでに接続してあるsocketからデータが送られてきた場合と非同期に発生するので
一つの関数で何が起こったかを調べることになります。
ここのチャットサーバでは、その関数にselect()という関数とepoll()という関数の2種類を使えるようにしています。

(続く)

http://chattera.net/
スポンサーサイト

コメントの投稿

非公開コメント

プロフィール

chattera.net

Author:chattera.net
フリーでソフト開発の仕事をしています。
自作したこのチャットシステムは、何か世の中に役に立つこともあるかと思いますので、お呼びがかかるとうれしいですね。

連絡先は chatteranet@gmail.com です。

また、ソフト開発関連のお誘いもうけたまわっております。

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QR