2015年1月10日土曜日

開発環境

Head First C ―頭とからだで覚えるCの基本(David Griffiths (著)、Dawn Griffiths (著) 中田 秀基(監訳)(翻訳)、木下 哲也 (翻訳)、オライリージャパン)の11章(ソケットとネットワーキング: 127.0.0.1という場所はない)、自分で考えてみよう(p.487)を解いてみる。

その他参考書籍

自分で考えてみよう(p.487)

コード(BBEdit, Emacs)

sample487.c

#include <string.h>

#include <stopif.h>
#include <catch_signal.h>

#include "sample478.h"

int open_listener_socket() {
  int s = socket(PF_INET, SOCK_STREAM, 0);
  Stopif(s == -1, exit(1), "ソケットを開けません: %s", strerror(errno));
  return s;
}

void bind_to_port(int socket, int port) {
  struct sockaddr_in name;
  name.sin_family = PF_INET;
  name.sin_port = (in_port_t)htons(port);
  name.sin_addr.s_addr = htonl(INADDR_ANY);
  int reuse = 1;
  Stopif(setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse,
                    sizeof(int)) == -1,
         exit(1),
         "ソケットに再利用オプションを設定できません。: %s", strerror(errno));
  int c = bind(socket, (struct sockaddr *) &name, sizeof(name));
  Stopif(c == -1, exit(1), "ソケットにバインドできません。: %s", strerror(errno));
}

int say(int socket, char *s) {
  int result = send(socket, s, strlen(s), 0);
  Stopif(result == -1, return result,
         "クライアントの通信エラー: %s", strerror(errno));
  return result;
}
                    
int main() {
  catch_signal(SIGINT, handle_shutdown);
  listener_d = open_listener_socket();
  bind_to_port(listener_d, 30000);
  Stopif(listen(listener_d, 10) == -1, exit(1),
         "接続待ちできません: %s", strerror(errno));
  printf("接続を待っています\n");
  while (1) {
    struct sockaddr_storage client_addr;
    unsigned int address_size = sizeof(client_addr);
    int connect_d = accept(listener_d, (struct sockaddr *)&client_addr,
                           &address_size);
    Stopif(connect_d == -1, exit(1),
           "第2のソケットを開けません: %s", strerror(errno));
    if (!fork()) {
      close(listener_d);
      if (say(connect_d, "Knock! Knock!\r\n") != -1) {
        char buf[255];
        read_in(connect_d, buf, sizeof(buf));
        if (strncasecmp("Who's there?", buf, 12) == 0) {
          if (say(connect_d, "Oscar\r\n") != -1) {
            read_in(connect_d, buf, sizeof(buf));
            if (strncasecmp("Oscar who?", buf, 10) == 0)
              say(connect_d,
                  "oscar silly question, you get a silly answer\r\n");
          }
        }
      }
      close(connect_d);
      exit(0);
    }
    close(connect_d);
  }
}  

入出力結果(Terminal)

サーバー

$ ./sample487
接続を待っています
^Cさようなら!
$

クライアント1

$ telnet 127.0.0.1 30000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Knock! Knock!
Who's there?
Oscar
Oscar who?
oscar silly question, you get a silly answer
Connection closed by foreign host.
$

クライアント2

$ telnet 127.0.0.1 30000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Knock! Knock!
Who's there?
Oscar
Oscar who?
oscar silly question, you get a silly answer
Connection closed by foreign host.
$

0 コメント:

コメントを投稿