2017 ソフトウェア設計及び演習用の班Wiki

17::gr10::サーバー班

サーバープログラム

  • クライアントから送られたデータをそのまま全クライアント(送ったきたクライアントを除く)に送信する。
  • IOチャネルではクライアントのファイル識別子の取得が分からなかったため、ソケットにより通信を実装している。
  • ソケットの監視はselect関数で実装。ループ毎にselectを実行している。
  • gtkとの統合は、ループ文をn秒毎に実行することで実現可能と考えている。
  • サーバー自体は操作しない上にデータを受け取って流すだけだからgtkで実装する必要はない?

バグ

どうやらクライアントのプロセスを強制終了(Ctrl+C)すると、何もないデータをサーバーが受信し続ける。
つまり strlen(msg) == 0 のデータ。強制終了させないことはできないので、条件分岐によってソケットを閉じる処理を追加した。

クライアントプログラム

  • stdinからの入力を監視し、入力を取得したらサーバーに送信する。
  • ソケットの監視はサーバーと同様の処理で監視。
  • 名前とメッセージの結合を行なった後に送信する。
  • サーバーと同様に長さ0データを受け取った時はソケットを閉じる処理を追加した。
  • 送信はキーボードのイベントで実行、受信はn秒毎の実行で統合できるかと。

バグ

入力中にメッセージが到着すると入力中のメッセージの続きに到着したメッセージが表示される。綺麗に表示したいならブロッキングする必要があり、すぐにメッセージを表示できなくなる。今回はメッセージの滑らかな表示を優先させた。どうやらターミナルの表示制御があるらしい(未確認、クライアントはgtkに統合されちゃうからまあ良いかなと思いました)

ブロッキングとノンブロッキング

scanfをループ中に実行するとプログラムが止まって、入力待ちとなる。この状態ではメッセージを受け取る関数も動かすことができない。readなども同様に受診を待つ。
ブロッキングせずにメッセージの受け取りと入力を行うためにはソケット(ファイル識別子)にデータが届いているかをチェックし、届いた時にだけ読み込みするようにしたい。 そのデータが届いているかのファイル識別子の監視をselect関数で行う。

  • select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds,struct timeval *timeout);
    • nfdsはファイル識別子集合の最大値+1
    • readfdsはreadfsに入ってるファイル識別子を監視する。データが到着したファイル識別子集合がセットされ返される。
    • writefdsはreadfdsと同様に書き込み可能かを監視する。
    • exceptfdsは例外の監視を行う
    • timeoutはタイムアウトするまでの時間を指定するtimeval構造体
    • 監視したいファイル識別子がない場合はNULLを指定する。

ファイル識別子集合を操作するマクロ

  • FD_ZERO()
    • ファイル識別子集合の削除
  • FD_SET()
    • 指定したファイル識別子を集合へ追加する
  • FD_CLR()
    • 指定したファイル識別子を集合から削除する
  • FD_ISSET()
    • 指定したファイル識別子が集合の中にあるかを調べる

今後の課題

  • キャラクターの座標をどうするか。
  • IOチャネルを用いていないため統合に苦労する?


最終更新日:2017/06/15 21:04:48