//////////////////////////////////////////////////////////////////////
// ishitori.h
//////////////////////////////////////////////////////////////////////
#ifndef _ISHITORI_H_
#define _ISHITORI_H_
#define SERVER_PORT 35000
#define BUFSIZE 1024
#define INIT_STONE_NUM 21
#define STONE_SYMBOL "●"
int read_stone_num(char *from, int *stone_left);
void print_stone_symbol(int num);
void handle_error(char *func, char *msg);
#endif /* _ISHITORI_H_ */
//////////////////////////////////////////////////////////////////////
// ishitori.c
//////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include "ishitori.h"
void handle_error(char *fname, char *msg)
{
fprintf(stderr, "%s() failed: %s\n", fname, msg);
exit(1);
}
int read_stone_num(char *from, int *stone_left)
{
int n = -1;
print_stone_symbol(*stone_left);
for (;;) {
printf("%s: いくつ石を取りますか? (1~3): ", from);
scanf("%d", &n);
if (0 < n && n <= 3) {
if (n > *stone_left) {
/* 残りの石の数よりも大きい値を取ろうとした場合 */
n = *stone_left;
}
printf("%d個取りました\n", n);
*stone_left -= n;
print_stone_symbol(*stone_left);
break;
}
printf("1~3個入力して下さい\n");
}
return *stone_left;
}
void print_stone_symbol(int num)
{
int i;
if (num < 0) { return; }
printf("Stones: ");
for (i = 0; i < num; i++) {
printf("%s", STONE_SYMBOL);
}
printf("[残り%d個]\n", num);
return;
}
//////////////////////////////////////////////////////////////////////
// ishitori_server.c
//////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include "ishitori.h"
static int setup_server(void);
int main(void)
{
int connfd = -1;
int n;
int stone_left = INIT_STONE_NUM;
char buf[BUFSIZE] = { 0, };
connfd = setup_server();
for (;;) {
/* サーバが最初に石を取る */
if (read_stone_num("Server", &stone_left) <= 0) {
/* サーバの負け */
printf("Server の負け\n");
break;
}
snprintf(buf, BUFSIZE, "%d", stone_left);
/* クライアントへ送信 */
if (write(connfd, buf, strlen(buf)) < 0) {
close(connfd);
handle_error("write", strerror(errno));
}
/* クライアントから受信 */
if ((n = read(connfd, buf, BUFSIZE)) > 0) {
stone_left = atoi(buf);
}
else if (n == 0) {
break;
}
else {
close(connfd);
handle_error("read", strerror(errno));
}
}
close(connfd);
return 0;
}
static int setup_server(void)
{
int listenfd = -1, connfd = -1;
struct sockaddr_in server_addr, client_addr;
int client_len = sizeof(client_addr);
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
handle_error("socket", strerror(errno));
}
memset(&server_addr, 0, sizeof(struct sockaddr_in));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(SERVER_PORT);
if (bind(listenfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in)) < 0) {
close(listenfd);
handle_error("bind", strerror(errno));
}
if (listen(listenfd, 1) < 0) {
close(listenfd);
handle_error("listen", strerror(errno));
}
if ((connfd = accept(listenfd, (struct sockaddr *)&client_addr, &client_len)) < 0) {
close(listenfd);
handle_error("accept", strerror(errno));
}
close(listenfd);
return connfd;
}
//////////////////////////////////////////////////////////////////////
// ishitori_client.c
//////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include "ishitori.h"
static int setup_client(char *ip_address);
int main(int argc, char *argv[])
{
int sockfd = -1;
int n;
char buf[BUFSIZE] = { 0, };
int stone_left = -1;
if (argc != 2) {
fprintf(stderr, "usage: ishitori_client serverIP\n");
exit(1);
}
sockfd = setup_client(argv[1]);
for (;;) {
/* サーバが最初にデータを送ってくる */
if ((n = read(sockfd, buf, BUFSIZE)) > 0) {
stone_left = atoi(buf);
}
else if (n == 0) {
break;
}
else {
close(sockfd);
handle_error("read", strerror(errno));
}
/* 石の個数を標準入力から読み込む */
if (read_stone_num("Client", &stone_left) <= 0) {
/* クライアントの負け */
printf("Client の負け\n");
break;
}
snprintf(buf, BUFSIZE, "%d", stone_left);
/* サーバへ送信 */
if ((n = write(sockfd, buf, strlen(buf))) < 0) {
close(sockfd);
handle_error("write", strerror(errno));
}
}
close(sockfd);
return 0;
}
static int setup_client(char *ip_address)
{
struct sockaddr_in server_addr;
int sockfd = -1;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
handle_error("socket", strerror(errno));
}
memset(&server_addr, 0, sizeof(struct sockaddr_in));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT);
if (inet_pton(AF_INET, ip_address, &server_addr.sin_addr) != 1) {
close(sockfd);
handle_error("inet_pton", strerror(errno));
}
if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in)) < 0) {
close(sockfd);
handle_error("connect", strerror(errno));
}
return sockfd;
}