------------------------- c_setup.cpp -------------------------
/******************************************/
/* ソケットの初期設定(クライアント) */
/* return : ソケットのディスクリプタ */
/******************************************/
#include <stdio.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
//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;
}
------------------------- html.cpp (main) -------------------------
/****************************/
/* HTTPクライアント */
/* coded by Y.Suganuma */
/****************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> // fork, read, write, open, close
#include <netinet/in.h> // in_port_t, sockaddr_in等
#define BUF_LEN 512 // バッファサイズ
#define PORT 80 // ポート番号
//int c_setup(char *, in_port_t);
int c_setup(char *, int); // コンパイラのバージョンによっては,
// 上の行の代わりにこの行を使用
int main(int argc, char *argv[])
{
int n;
int client_socket; // 送受信用のソケット
char buf[BUF_LEN]; // 送受信用バッファ
char hostname[50] = "cs-www"; // ホスト名
char adr[100] = "/suganuma/index.html"; // ファイル名
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;
}
クライアント側のプログラム
------------------------- c_setup.cpp -------------------------
/******************************************/
/* ソケットの初期設定(クライアント) */
/* hostname : サーバ名 */
/* port : ポート番号 */
/* return : ソケットのディスクリプタ */
/******************************************/
#include <stdio.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等
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;
}
------------------------- client1.cpp (main) -------------------------
/********************************/
/* ファイル転送(クライアント) */
/* coded by Y.Suganuma */
/********************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // 文字列操作,memset,FD_ZERO等
#include <fcntl.h> // O_RDONLY等
#include <unistd.h> // fork, read, write, open, close
#include <netinet/in.h> // in_port_t, sockaddr_in等
#define BUF_LEN 512 // バッファサイズ
#define PORT 50000 // ポート番号
int c_setup(char *, in_port_t);
//int c_setup(char *, int); // コンパイラのバージョンによっては,
// 上の行の代わりにこの行を使用
int main(int argc, char *argv[])
{
int n, sw, in;
int client_socket; // 送受信用のソケット
char buf[BUF_LEN]; // 送受信用バッファ
char hostname[50]; // ホスト名
/*
サーバ名
*/
if (argc != 2) {
printf("***error*** サーバ名を入力してください\n");
exit(1);
}
else
strcpy(hostname, argv[1]);
/*
初期設定
*/
if ((client_socket = c_setup(hostname, PORT)) == -1) {
printf("***error*** 接続できませんでした\n");
exit(1);
}
/*
ファイル名の入力とファイル内容の転送
*/
// ファイル名の入力
n = read(client_socket, buf, BUF_LEN);
write(1, buf, n);
scanf("%s", buf);
// ファイル名の送信
in = open(buf, O_RDONLY);
// 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);
// ファイル内容の送信
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;
}
サーバ側のプログラム
------------------------- s_setup.cpp -------------------------
/************************************/
/* ソケットの初期設定(サーバ) */
/* port : ポート番号 */
/* return : リスニングソケット */
/************************************/
#include <stdio.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等
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;
}
------------------------- e_ftp.cpp -------------------------
/********************************************/
/* ftpの実行 */
/* connected_socket : 接続済みソケット */
/********************************************/
#include <stdio.h>
#include <fcntl.h> // O_RDONLY等
#include <sys/socket.h> // ソケット(AF_INET, select等)
#include <netdb.h> // ソケット(inet_ntoa等)
#include <arpa/inet.h> // ソケット(sockaddr_in等)
#include <unistd.h> // fork, read, write, open, close
#include <netinet/in.h> // in_port_t, sockaddr_in等
#define BUF_LEN 512 // バッファサイズ
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);
}
------------------------- server1.cpp (main) -------------------------
/****************************/
/* ファイル転送(サーバ) */
/* coded by Y.Suganuma */
/****************************/
#include <stdio.h>
#include <stdlib.h>
#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 PORT 50000 // ポート番号
int s_setup(in_port_t);
//int s_setup(int); // コンパイラのバージョンによっては,
// 上の行の代わりにこの行を使用
void e_ftp(int);
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;
}
クライアント側のプログラム
------------------------- c_setup.cpp -------------------------
/******************************************/
/* ソケットの初期設定(クライアント) */
/* hostname : サーバ名 */
/* port : ポート番号 */
/* return : ソケットのディスクリプタ */
/******************************************/
#include <stdio.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等
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;
}
------------------------- prepare.cpp -------------------------
/***************************************/
/* 会話のための準備 */
/* soc : ソケットのディスクリプタ */
/* return : select用初期化マスク */
/***************************************/
#include <sys/types.h> // fd_set
#include <string.h> // 文字列操作,memset,FD_ZERO等
fd_set prepare(int soc)
{
fd_set mask;
/*
マスクの準備
*/
FD_ZERO(&mask);
FD_SET(0, &mask); // ディスクリプタ0(キーボード)をセット
FD_SET(soc, &mask); // ソケットのディスクリプタをセット
return mask;
}
------------------------- chat.cpp -------------------------
/**************************************/
/* 会話 */
/* fd : ソケットのディスクリプタ */
/* buf : バッファ */
/* size : バッファサイズ */
/* mask : select用初期化マスク */
/**************************************/
#include <stdio.h>
#include <sys/types.h> // fd_set
#include <string.h> // 文字列操作,memset,FD_ZERO等
#include <sys/socket.h> // ソケット(AF_INET, select等)
#include <unistd.h> // fork, read, write, open, close
void chat(int fd, char *buf, int size, fd_set mask)
{
int n, sw = 1;
fd_set now;
while (sw > 0) {
// マスクの初期化
now = mask;
select(fd+1, (fd_set*)&now, NULL, NULL, NULL);
// キーボードからの入力チェック
if (FD_ISSET(0, &now)) {
gets(buf);
n = strlen(buf);
if (n > 0)
write(fd, buf, n); // 送信
}
// ソケット内のデータを調べる
if (FD_ISSET(fd, &now)) {
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);
}
}
}
------------------------- client2.cpp (main) -------------------------
/**********************************/
/* チャットルーム(クライアント) */
/* coded by Y.Suganuma */
/**********************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h> // fd_set
#include <unistd.h> // fork, read, write, open, close
#include <netinet/in.h> // in_port_t, sockaddr_in等
#define BUF_LEN 512 // バッファサイズ
#define PORT 50000 // ポート番号
void chat(int, char *, int, fd_set);
fd_set prepare(int);
int c_setup(char *, in_port_t);
//int c_setup(char *, int); // コンパイラのバージョンによっては,
// 上の行の代わりにこの行を使用
int main(int argc, char *argv[])
{
int n;
int client_socket; // 送受信用のソケット
char buf[BUF_LEN]; // 送受信用バッファ
char hostname[50]; // ホスト名
fd_set mask; // 相手を選択する(select)ための初期化マスク
/*
サーバ名
*/
if (argc != 2) {
printf("***error*** サーバ名を入力してください\n");
exit(1);
}
else
strcpy(hostname, argv[1]);
/*
初期設定
*/
if ((client_socket = c_setup(hostname, PORT)) == -1) {
printf("***error*** 接続できませんでした\n");
exit(1);
}
/*
参加登録
*/
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);
// サーバとクライアントが会話を行うための準備(マスクの設定)
mask = prepare(client_socket);
// チャットの実行
chat(client_socket, buf, BUF_LEN, mask);
}
return 0;
}
サーバ側のプログラム
------------------------- member.h -------------------------
/**************/
/* 参加者情報 */
/**************/
class Member {
public:
int state; // 回線の状態(1 : 開, 0 : 閉)
int fd; // ソケットディスクリプタ
char name[50]; // 参加者名
Member(); // コンストラクタ
};
------------------------- Member.cpp -------------------------
/********************************/
/* クラスmemberのコンストラクタ */
/********************************/
#include "member.h"
Member::Member()
{
state = 0;
}
------------------------- s_setup.cpp -------------------------
/************************************/
/* ソケットの初期設定(サーバ) */
/* port : ポート番号 */
/* w_no : 待ち受けの最大数 */
/* return : リスニングソケット */
/************************************/
#include <stdio.h>
#include <string.h> // 文字列操作,memset,FD_ZERO等
#include <sys/socket.h> // ソケット(AF_INET, select等)
#include <netinet/in.h> // in_port_t, sockaddr_in等
int s_setup(in_port_t port, int w_no)
//int s_setup(int port, int w_no)
// コンパイラのバージョンによっては,上の行の代わりにこの行を使用
{
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, w_no) == -1 )
printf("***error*** 待ち受けに失敗しました\n");
}
}
return listening_socket;
}
------------------------- init.cpp -------------------------
/************************************/
/* 参加者の登録と初期設定 */
/* soc : 接続済みソケット */
/* w_no : 待ち受けの最大数 */
/* mask : select用初期化マスク */
/* no : 現在の接続数 */
/* mem : 接続登録簿 */
/* return : 現在の接続数 */
/************************************/
#include <string.h> // 文字列操作,memset,FD_ZERO等
#include <sys/types.h> // fd_set
#include <unistd.h> // read, write, open, close
#include "member.h"
int init(int soc, int w_no, fd_set *mask, int no, Member **mem)
{
int i1, sw = 0;
// 満員
if (no == w_no) {
write(soc, "満員ですので,後ほどご利用下さい\n", 33);
close(soc);
}
// 参加できる
else {
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.cpp -------------------------
/**********************************************/
/* チャットの実行 */
/* w_no : 待ち受けの最大数 */
/* max_fd : ソケットの最大ディスクリプタ */
/* buf : バッファ */
/* size : バッファサイズ */
/* mask : select用初期化マスク */
/* no : 現在の接続数 */
/* mem : 各ソケットの状態 */
/* listening_socket : リスニングソケット */
/**********************************************/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h> // fd_set
#include <string.h> // 文字列操作,memset,FD_ZERO等
#include <sys/socket.h> // ソケット(AF_INET, select等)
#include <unistd.h> // read, write, open, close
#include "member.h"
#define BUF_LEN_TMP 562 // バッファの大きさ
int init(int, int, fd_set *, int, Member **);
int chat(int w_no, int *max_fd, char *buf, int size, fd_set *mask,
int no, Member **mem, int listening_socket)
{
int i1, i2, k, len, n, sw = 1;
char str[BUF_LEN_TMP];
int connected_socket; // 接続済みソケット
fd_set now;
// マスクの初期化と事象の選択
now = *mask;
select((*max_fd)+1, (fd_set *)&now, NULL, NULL, NULL);
// 新規のクライアント登録
if (FD_ISSET(listening_socket, &now)) {
if ((connected_socket = accept(listening_socket, NULL, NULL)) != -1) {
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);
}
}
// チャットの終了チェック
if (FD_ISSET(0, &now)) { // キーボードからの入力チェック
gets(buf);
if (strcmp(buf, "quit") == 0) {
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) {
for (i1 = 0; i1 < w_no; i1++) {
if (mem[i1]->state > 0 && FD_ISSET(mem[i1]->fd, &now)) {
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;
for (i2 = 0; i2 < w_no; i2++) {
if (mem[i2]->state > 0 && mem[i2]->fd > *max_fd)
*max_fd = mem[i2]->fd;
}
no--;
}
// チャットの続行
else {
len = strlen(mem[i1]->name);
strcpy(str, mem[i1]->name);
strcat(str, buf);
strcat(str, "\n");
for (i2 = 0; i2 < w_no; i2++) {
if (mem[i2]->state > 0)
write(mem[i2]->fd, str, n+len+1);
}
}
}
}
}
return no;
}
------------------------- server2.cpp (main) -------------------------
/****************************/
/* チャットルーム(サーバ) */
/* coded by Y.Suganuma */
/****************************/
#include <stdio.h>
#include <stdlib.h> // atoi等
#include <string.h> // 文字列操作,memset,FD_ZERO等
#include <sys/types.h> // fd_set
#include <sys/socket.h> // ソケット(AF_INET, select等)
#include <netinet/in.h> // in_port_t, sockaddr_in等
#include <unistd.h> // read, write, open, close
#include "member.h"
#define PORT 50000 // ポート番号
#define BUF_LEN 512 // バッファの大きさ
int chat(int, int *, char *, int, fd_set *, int, Member **, int);
int s_setup(in_port_t, int);
//int s_setup(int, int);
// コンパイラのバージョンによっては,上の行の代わりにこの行を使用
int main(int argc, char *argv[])
{
int i1, no = 0, max = 0, sw = 1;
char buf[BUF_LEN]; // バッファ
int listening_socket; // リスニングソケットソケット
int max_fd; // 接続済みソケットの最大ディスクリプタ
fd_set mask;
Member **mem;
/*
最大参加者数
*/
if (argc != 2) {
printf("***error*** 参加者数を入力してください\n");
exit(1);
}
else
max = atoi(argv[1]);
/*
リスニングソケットの準備
*/
if ((listening_socket = s_setup(PORT, max)) == -1) {
printf("***error*** リスニング接続に失敗しました\n");
exit(1);
}
/*
参加登録簿とマスクの準備
*/
mem = new Member * [max];
for (i1 = 0; i1 < max; i1++)
mem[i1] = new Member;
max_fd = listening_socket;
FD_ZERO(&mask);
FD_SET(0, &mask); // ディスクリプタ0(キーボード)をセット
FD_SET(listening_socket, &mask); // リスニングソケットをセット
/*
チャットの実行
*/
printf("Ready to Chat\n");
while (sw > 0) {
no = chat(max, &max_fd, buf, BUF_LEN, &mask, no, mem, listening_socket);
if (no < 0) {
sw = 0;
close(listening_socket);
}
}
return 0;
}