情報学部 | 菅沼ホーム | 全体目次 | 演習解答例 | 付録 | 索引 |
ポート番号 | ポート名 | 用途 |
---|---|---|
20 | ftp data | File Transfer Protocolのデータ用ポート |
21 | ftp | File Transfer Protocolの制御用ポート |
23 | telnet | Telnet Protocol |
80 | http | http |
25 | smtp | Simple Mail Transfer Protocol |
110 | pop3 | Post Office Protocol version 3 |
119 | nntp | Network News Transfer Protocol |
123 | ntp | Network Time Protocol |
#include <stdio.h> #include <stdlib.h> #include <string.h> // 文字列操作,memset,FD_ZERO等 #include <netdb.h> // ソケット(hostent等) #include <sys/socket.h> // ソケット(AF_INET, select等) #include <netinet/in.h> // in_port_t, sockaddr_in等 #include <unistd.h> // fork, read, write, open, close #define BUF_LEN 512 // バッファサイズ #define PORT 80 // ポート番号 /************************************************/ /* ソケットの初期設定(クライアント,c_setup ) */ /* return : ソケットのディスクリプタ */ /************************************************/ //int c_setup(char *hostname, in_port_t port) int c_setup(char *hostname, int port) // コンパイラのバージョンによっては, // 上の行の代わりにこの行を使用 { int client_socket = -1; // ソケット hostent *server_inf1; // クライアント情報1 sockaddr_in server_inf2; // クライアント情報2 /* サーバ名からサーバ情報を得る */ if ((server_inf1 = gethostbyname(hostname)) == NULL) printf("***error*** サーバ名が不適当です\n"); /* サーバ情報をsockaddr_in構造体に設定 */ else { memset((char *)&server_inf2, 0, sizeof(server_inf2)); server_inf2.sin_family = AF_INET; // アドレスファミリー server_inf2.sin_port = htons(port); // htons(2バイト) // 整数の上位及び下位バイトの指定 memcpy((char *)&server_inf2.sin_addr.s_addr, server_inf1->h_addr, server_inf1->h_length); /* ソケットを作成 */ if ((client_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) printf("***error*** socketを作成できませんでした\n"); /* サーバへ接続 */ else { if (connect(client_socket, (sockaddr *)&server_inf2, sizeof(server_inf2)) == -1) client_socket = -1; } } return client_socket; } /*******************************/ /* HTTP クライアント( main ) */ /* coded by Y.Suganuma */ /*******************************/ int main(int argc, char *argv[]) { int n; int client_socket; // 送受信用のソケット char buf[BUF_LEN]; // 送受信用バッファ char hostname[50] = "informatics.sist.ac.jp"; // ホスト名 char adr[100] = "/suganuma/master.css"; // ファイル名 char buf1[20]; /* 初期設定 */ if ((client_socket = c_setup(hostname, PORT)) == -1) { printf("***error*** 接続できませんでした\n"); exit(1); } /* サーバとの送信 */ else { // 送信内容の指定(サーバに対するリクエスト) strcpy(buf, "GET "); strcat(buf, adr); strcat(buf, " HTTP/1.1\r\n"); write(client_socket, buf, strlen(buf)); // ホスト名とポート strcpy(buf, "Host: "); strcat(buf, hostname); strcat(buf, ":"); gcvt((double)PORT, 10, buf1); strcat(buf, buf1); strcat(buf, "\r\n"); write(client_socket, buf, strlen(buf)); // リクエスト(GET)の終了 strcpy(buf, "\r\n"); write(client_socket, buf, strlen(buf)); // 受信内容の表示 n = 1; while (n > 0) { n = read(client_socket, buf, BUF_LEN); if (n > 0) write(1, buf, n); } } close(client_socket); return 0; }
GET /suganuma/master.css HTTP/1.1\r\n // 送信内容の指定 Host: cs-www:80\r\n // ホスト名とポート \r\n // リクエスト(GET)の終了
#include <stdio.h> #include <stdlib.h> #include <string.h> // 文字列操作,memset,FD_ZERO等 #include <netdb.h> // ソケット(hostent等) #include <sys/socket.h> // ソケット(AF_INET, select等) #include <netinet/in.h> // in_port_t, sockaddr_in等 #include <fcntl.h> // O_RDONLY等 #include <unistd.h> // fork, read, write, open, close #define BUF_LEN 512 // バッファサイズ #define PORT 50000 // ポート番号 /************************************************/ /* ソケットの初期設定(クライアント,c_setup ) */ /* hostname : サーバ名 */ /* port : ポート番号 */ /* return : ソケットのディスクリプタ */ /************************************************/ int c_setup(char *hostname, in_port_t port) //int c_setup(char *hostname, int port) // コンパイラのバージョンによっては, // 上の行の代わりにこの行を使用 { int client_socket = -1; // ソケット /* サーバ名からサーバ情報を得る */ hostent *server_inf1; // サーバ情報1 if ((server_inf1 = gethostbyname(hostname)) == NULL) printf("***error*** サーバ名が不適当です\n"); /* サーバ情報をsockaddr_in構造体に設定 */ else { sockaddr_in server_inf2; // サーバ情報2 memset((char *)&server_inf2, 0, sizeof(server_inf2)); server_inf2.sin_family = AF_INET; // アドレスファミリー server_inf2.sin_port = htons(port); // htons(2バイト) // 整数の上位及び下位バイトの指定 memcpy((char *)&server_inf2.sin_addr.s_addr, server_inf1->h_addr, server_inf1->h_length); /* ソケットを作成 */ if ((client_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) printf("***error*** socketを作成できませんでした\n"); /* サーバへ接続 */ else { if (connect(client_socket, (sockaddr *)&server_inf2, sizeof(server_inf2)) == -1) client_socket = -1; } } /* ディスクリプタを返す */ return client_socket; } /***************************************/ /* ファイル転送(クライアント,main ) */ /* coded by Y.Suganuma */ /***************************************/ int main(int argc, char *argv[]) { /* サーバ名 */ char hostname[50]; // ホスト名 if (argc != 2) { printf("***error*** サーバ名を入力してください\n"); exit(1); } else strcpy(hostname, argv[1]); /* 初期設定 */ int client_socket; // 送受信用のソケット if ((client_socket = c_setup(hostname, PORT)) == -1) { printf("***error*** 接続できませんでした\n"); exit(1); } /* ファイル名の入力とファイル内容の転送 */ // ファイル名の入力 char buf[BUF_LEN]; // 送受信用バッファ int n = read(client_socket, buf, BUF_LEN); write(1, buf, n); scanf("%s", buf); // ファイル名の送信 int in = open(buf, O_RDONLY); // int in = open(buf, O_BINARY | O_RDONLY); // OS(MS-DOSなど)によっては,上の行の代わりにこの行を使用しないと // バイナリファイルを正しく送信できない. if (in < 0) { printf("***error*** ファイルが存在しません\n"); close(client_socket); exit(1); } write(client_socket, buf, strlen(buf)+1); // ファイル内容の送信 int sw = 1; while (sw > 0) { n = read(in, buf, BUF_LEN); if (n > 0) write(client_socket, buf, n); else sw = 0; } /* 接続を切り,ファイルを閉じる */ close(client_socket); close(in); return 0; }
#include <stdio.h> #include <stdlib.h> #include <string.h> // 文字列操作,memset,FD_ZERO等 #include <sys/socket.h> // ソケット(AF_INET, select等) #include <arpa/inet.h> // ソケット(sockaddr_in等) #include <netinet/in.h> // in_port_t, sockaddr_in等 #include <fcntl.h> // O_RDONLY等 #include <sys/socket.h> // ソケット(AF_INET, select等) #include <netdb.h> // ソケット(inet_ntoa等) #include <unistd.h> // fork, read, write, open, close #define BUF_LEN 512 // バッファサイズ #define PORT 50000 // ポート番号 /******************************************/ /* ソケットの初期設定(サーバ,s_setup ) */ /* port : ポート番号 */ /* return : リスニングソケット */ /******************************************/ int s_setup(in_port_t port) //int s_setup(int port) // コンパイラのバージョンによっては, // 上の行の代わりにこの行を使用 { int listening_socket = -1; // リスニングソケット sockaddr_in server_inf; // サーバ情報 /* サーバ情報をsockaddr_in構造体に設定 */ memset((char *)&server_inf, 0, sizeof(server_inf)); server_inf.sin_family = AF_INET; // アドレスファミリー server_inf.sin_addr.s_addr = htonl(INADDR_ANY); // IPアドレス server_inf.sin_port = htons(port); // htonl(4バイト),htons(2バイト) // 整数の上位及び下位バイトの指定 /* リスニングソケットを作成 */ if ((listening_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) printf("***error*** 接続できませんでした\n"); /* サーバのアドレスをソケットに設定する */ else { if (bind(listening_socket, (sockaddr *)&server_inf, sizeof(server_inf)) < 0) printf("***error*** 設定に失敗しました\n"); /* 待ち受ける(待機状態の準備)(第2引数は,待ち受けの数) */ else { if (listen(listening_socket, 1) == -1 ) printf("***error*** 待ち受けに失敗しました\n"); } } return listening_socket; } /********************************************/ /* ftpの実行( e_ftp ) */ /* connected_socket : 接続済みソケット */ /********************************************/ void e_ftp(int connected_socket) { int n, sw, out; char buf[BUF_LEN]; // 送受信用バッファ hostent *client_inf1; // クライアント情報1 sockaddr_in client_inf2; // クライアント情報2 socklen_t len; // int len; // コンパイラのバージョンによっては, // 上の行の代わりにこの行を使用 /* クライアント情報を取得できた場合,それを表示する */ len = (socklen_t)sizeof(client_inf2); // len = sizeof(client_inf2); // コンパイラのバージョンによっては, // 上の行の代わりにこの行を使用 getpeername(connected_socket, (sockaddr *)&client_inf2, &len); client_inf1 = gethostbyaddr((char *)&client_inf2.sin_addr.s_addr, sizeof(client_inf2.sin_addr), AF_INET); if (client_inf1 != NULL) { printf("%s と接続しました(IP: %s, ポート %d)\n", client_inf1->h_name, inet_ntoa(client_inf2.sin_addr), ntohs(client_inf2.sin_port)); } /* 送られてきたファイルを保存 */ // ファイル名 write(connected_socket, "ファイル名を入力してください ", 29); read(connected_socket, buf, BUF_LEN); // 保存 out = open(buf, O_WRONLY | O_CREAT, S_IREAD | S_IWRITE); // out = open(buf, O_BINARY | O_WRONLY | O_CREAT, S_IREAD | S_IWRITE); // OS(MS-DOSなど)によっては,上の行の代わりにこの行を使用しないと, // バイナリファイルを正しく送信できない. sw = 1; while (sw > 0) { n = read(connected_socket, buf, BUF_LEN); if (n > 0) write(out, buf, n); else sw = 0; } close(out); } /*********************************/ /* ファイル転送(サーバ,main ) */ /* coded by Y.Suganuma */ /*********************************/ int main() { int listening_socket; // リスニングソケット int connected_socket; // 接続済みソケット pid_t pid; // プロセスID /* リスニングソケットの生成 */ if ((listening_socket = s_setup(PORT)) != -1) { /* 接続待機 */ while(1) { // 接続済みソケット if ((connected_socket = accept(listening_socket, NULL, NULL)) != -1) { // 子プロセスの生成 // 子プロセス if ((pid = fork()) == 0) { close(listening_socket); e_ftp(connected_socket); close(connected_socket); exit(0); } // 親プロセス else close(connected_socket); } } } return 0; }
#include <stdio.h> #include <stdlib.h> #include <string.h> // 文字列操作,memset,FD_ZERO等 #include <netdb.h> // ソケット(hostent等) #include <sys/socket.h> // ソケット(AF_INET, select等) #include <netinet/in.h> // in_port_t, sockaddr_in等 #include <sys/types.h> // fd_set #include <unistd.h> // fork, read, write, open, close #define BUF_LEN 512 // バッファサイズ #define PORT 50000 // ポート番号 /************************************************/ /* ソケットの初期設定(クライアント,c_setup ) */ /* hostname : サーバ名 */ /* port : ポート番号 */ /* return : ソケットのディスクリプタ */ /************************************************/ int c_setup(char *hostname, in_port_t port) //int c_setup(char *hostname, int port) // コンパイラのバージョンによっては, // 上の行の代わりにこの行を使用 { int client_socket = -1; // 送受信用のソケット /* サーバ名からサーバ情報を得る */ hostent *server_inf1; // サーバ情報1 if ((server_inf1 = gethostbyname(hostname)) == NULL) printf("***error*** サーバ名が不適当です\n"); /* サーバ情報をsockaddr_in構造体に設定 */ else { sockaddr_in server_inf2; // サーバ情報2 memset((char *)&server_inf2, 0, sizeof(server_inf2)); server_inf2.sin_family = AF_INET; // アドレスファミリー server_inf2.sin_port = htons(port); // htons(2バイト) // 整数の上位及び下位バイトの指定 memcpy((char *)&server_inf2.sin_addr.s_addr, server_inf1->h_addr, server_inf1->h_length); /* ソケットを作成 */ if ((client_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) printf("***error*** socketを作成できませんでした\n"); /* サーバへ接続 */ else { if (connect(client_socket, (sockaddr *)&server_inf2, sizeof(server_inf2)) == -1) client_socket = -1; } } /* ディスクリプタを返す */ return client_socket; } /***************************************/ /* 会話のための準備( prepare ) */ /* soc : ソケットのディスクリプタ */ /* return : select用初期化マスク */ /***************************************/ fd_set prepare(int soc) { fd_set mask; /* マスクの準備 */ FD_ZERO(&mask); FD_SET(0, &mask); // ディスクリプタ0(キーボード)をセット FD_SET(soc, &mask); // ソケットのディスクリプタをセット return mask; } /**************************************/ /* 会話( chat ) */ /* fd : ソケットのディスクリプタ */ /* buf : バッファ */ /* size : バッファサイズ */ /* mask : select用初期化マスク */ /**************************************/ void chat(int fd, char *buf, int size, fd_set mask) { int sw = 1; while (sw > 0) { // マスクの初期化 fd_set now = mask; select(fd+1, (fd_set*)&now, NULL, NULL, NULL); // キーボードからの入力チェック if (FD_ISSET(0, &now)) { gets(buf); int n = strlen(buf); if (n > 0) write(fd, buf, n); // 送信 } // ソケット内のデータを調べる if (FD_ISSET(fd, &now)) { int n = read(fd, buf, size); buf[n] = '\0'; if (strcmp(buf, "Server.quit") == 0) { printf("チャットルームを閉じます!\n"); close(fd); sw = 0; } else if (strcmp(buf, "quit") == 0) { close(fd); sw = 0; } else write(1, buf, n); } } } /*****************************************/ /* チャットルーム(クライアント,main ) */ /* coded by Y.Suganuma */ /*****************************************/ int main(int argc, char *argv[]) { /* サーバ名 */ char hostname[50]; // ホスト名 if (argc != 2) { printf("***error*** サーバ名を入力してください\n"); exit(1); } else strcpy(hostname, argv[1]); /* 初期設定 */ int client_socket; // 送受信用のソケット if ((client_socket = c_setup(hostname, PORT)) == -1) { printf("***error*** 接続できませんでした\n"); exit(1); } /* 参加登録 */ char buf[BUF_LEN]; // 送受信用バッファ int n = read(client_socket, buf, BUF_LEN); // 参加者名の入力を促すメッセージ write(1, buf, n); buf[n] = '\0'; if (strstr(buf, "満員ですので,後ほどご利用下さい") != NULL) close(client_socket); else { gets(buf); // 参加者名の入力 write(client_socket, buf, strlen(buf)+1); n = read(client_socket, buf, BUF_LEN); // 「しばらくお待ち下さい」 write(1, buf, n); // サーバとクライアントが会話を行うための準備(マスクの設定) fd_set mask = prepare(client_socket); // 相手を選択する(select)ための初期化マスク // チャットの実行 chat(client_socket, buf, BUF_LEN, mask); } return 0; }
#include <stdio.h> #include <stdlib.h> // atoi等 #include <string.h> // 文字列操作,memset,FD_ZERO等 #include <sys/socket.h> // ソケット(AF_INET, select等) #include <netinet/in.h> // in_port_t, sockaddr_in等 #include <sys/types.h> // fd_set #include <unistd.h> // read, write, open, close #define BUF_LEN_TMP 562 // バッファの大きさ #define PORT 50000 // ポート番号 #define BUF_LEN 512 // バッファの大きさ /**************/ /* 参加者情報 */ /**************/ class Member { public: int state; // 回線の状態(1 : 開, 0 : 閉) int fd; // ソケットディスクリプタ char name[50]; // 参加者名 Member(); // コンストラクタ }; /********************************/ /* クラスMemberのコンストラクタ */ /********************************/ Member::Member() { state = 0; } /******************************************/ /* ソケットの初期設定(サーバ,s_setup ) */ /* port : ポート番号 */ /* w_no : 待ち受けの最大数 */ /* return : リスニングソケット */ /******************************************/ int s_setup(in_port_t port, int w_no) //int s_setup(int port, int w_no) // コンパイラのバージョンによっては,上の行の代わりにこの行を使用 { /* サーバ情報をsockaddr_in構造体に設定 */ sockaddr_in server_inf; // サーバ情報 memset((char *)&server_inf, 0, sizeof(server_inf)); server_inf.sin_family = AF_INET; // アドレスファミリー server_inf.sin_addr.s_addr = htonl(INADDR_ANY); // IPアドレス server_inf.sin_port = htons(port); // htonl(4バイト),htons(2バイト) // 整数の上位及び下位バイトの指定 /* リスニングソケットを作成 */ int listening_socket = -1; // リスニングソケットソケット if ((listening_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) printf("***error*** 接続できませんでした\n"); /* サーバのアドレスをソケットに設定する */ else { if (bind(listening_socket, (sockaddr *)&server_inf, sizeof(server_inf)) < 0) printf("***error*** 設定に失敗しました\n"); /* 待ち受ける(待機状態の準備)(第2引数は,待ち受けの数) */ else { if (listen(listening_socket, w_no) == -1 ) printf("***error*** 待ち受けに失敗しました\n"); } } return listening_socket; } /************************************/ /* 参加者の登録と初期設定( init ) */ /* soc : 接続済みソケット */ /* w_no : 待ち受けの最大数 */ /* mask : select用初期化マスク */ /* no : 現在の接続数 */ /* mem : 接続登録簿 */ /* return : 現在の接続数 */ /************************************/ int init(int soc, int w_no, fd_set *mask, int no, Member **mem) { // 満員 if (no == w_no) { write(soc, "満員ですので,後ほどご利用下さい\n", 33); close(soc); } // 参加できる else { int i1, sw = 0; for (i1 = 0; i1 < w_no && sw == 0; i1++) { if (mem[i1]->state == 0) { // ディスクリプタの登録 mem[i1]->state = 1; mem[i1]->fd = soc; no++; // マスクの設定 FD_SET(mem[i1]->fd, mask); // 参加者名 write(soc, "名前を入力して下さい ", 21); read(soc, mem[i1]->name, 50); strcat(mem[i1]->name, ": "); // 開始OK write(soc, "しばらくお待ち下さい\n", 21); write(soc, "チャット開始OKです!\n", 23); sw = 1; } } } return no; } /**********************************************/ /* チャットの実行( chat) */ /* w_no : 待ち受けの最大数 */ /* max_fd : ソケットの最大ディスクリプタ */ /* buf : バッファ */ /* size : バッファサイズ */ /* mask : select用初期化マスク */ /* no : 現在の接続数 */ /* mem : 各ソケットの状態 */ /* listening_socket : リスニングソケット */ /**********************************************/ int chat(int w_no, int *max_fd, char *buf, int size, fd_set *mask, int no, Member **mem, int listening_socket) { // マスクの初期化と事象の選択 fd_set now = *mask; select((*max_fd)+1, (fd_set *)&now, NULL, NULL, NULL); // 新規のクライアント登録 if (FD_ISSET(listening_socket, &now)) { int connected_socket; // 接続済みソケット if ((connected_socket = accept(listening_socket, NULL, NULL)) != -1) { int k = init(connected_socket, w_no, mask, no, mem); if (k > no) { no = k; if (connected_socket > *max_fd) *max_fd = connected_socket; } } else { printf("***error*** クライアントとの接続に失敗しました\n"); exit(1); } } // チャットの終了チェック int sw = 1; if (FD_ISSET(0, &now)) { // キーボードからの入力チェック gets(buf); if (strcmp(buf, "quit") == 0) { int i1; for (i1 = 0; i1 < w_no; i1++) { if (mem[i1]->state > 0) write(mem[i1]->fd, "Server.quit", 11); } for (i1 = 0; i1 < w_no; i1++) { if (mem[i1]->state > 0) close(mem[i1]->fd); } for (i1 = 0; i1 < w_no; i1++) delete [] mem[i1]; delete [] mem; sw = 0; no = -1; } } // 各ソケットを調べる if (sw > 0) { int i1; for (i1 = 0; i1 < w_no; i1++) { if (mem[i1]->state > 0 && FD_ISSET(mem[i1]->fd, &now)) { int n = read(mem[i1]->fd, buf, size); buf[n] = '\0'; // クライアントの終了 if (strcmp(buf, "quit") == 0) { write(mem[i1]->fd, "また参加して下さい!\n", 21); write(mem[i1]->fd, "quit", 4); FD_CLR(mem[i1]->fd, mask); close(mem[i1]->fd); mem[i1]->state = 0; *max_fd = -1; int i2; for (i2 = 0; i2 < w_no; i2++) { if (mem[i2]->state > 0 && mem[i2]->fd > *max_fd) *max_fd = mem[i2]->fd; } no--; } // チャットの続行 else { int len = strlen(mem[i1]->name); char str[BUF_LEN_TMP]; strcpy(str, mem[i1]->name); strcat(str, buf); strcat(str, "\n"); int i2; for (i2 = 0; i2 < w_no; i2++) { if (mem[i2]->state > 0) write(mem[i2]->fd, str, n+len+1); } } } } } return no; } /***********************************/ /* チャットルーム(サーバ,main ) */ /* coded by Y.Suganuma */ /***********************************/ int main(int argc, char *argv[]) { /* 最大参加者数 */ int max = 0; if (argc != 2) { printf("***error*** 参加者数を入力してください\n"); exit(1); } else max = atoi(argv[1]); /* リスニングソケットの準備 */ int listening_socket; // リスニングソケットソケット if ((listening_socket = s_setup(PORT, max)) == -1) { printf("***error*** リスニング接続に失敗しました\n"); exit(1); } /* 参加登録簿とマスクの準備 */ Member **mem = new Member * [max]; int i1; for (i1 = 0; i1 < max; i1++) mem[i1] = new Member; int max_fd = listening_socket; // 接続済みソケットの最大ディスクリプタ fd_set mask; FD_ZERO(&mask); FD_SET(0, &mask); // ディスクリプタ0(キーボード)をセット FD_SET(listening_socket, &mask); // リスニングソケットをセット /* チャットの実行 */ printf("Ready to Chat\n"); int sw = 1; while (sw > 0) { char buf[BUF_LEN]; // バッファ int no = chat(max, &max_fd, buf, BUF_LEN, &mask, no, mem, listening_socket); if (no < 0) { sw = 0; close(listening_socket); } } return 0; }
情報学部 | 菅沼ホーム | 全体目次 | 演習解答例 | 付録 | 索引 |