質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.51%

  • C

    4517questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • MacOS(OSX)

    2353questions

    MacOSとは、Appleの開発していたGUI(グラフィカルユーザーインターフェース)を採用したオペレーションシステム(OS)です。Macintoshと共に、市場に出てGUIの普及に大きく貢献しました。

  • TCP

    187questions

    TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。

  • UDP

    74questions

    UDP(User Datagram Protocol)とは、トランスポート層のプロトコルであり、コネクション型のデータサービスです。IPネットワーク上の別のホストにコンピュータのアプリケーションがメッセージを送ることができ、転送チャンネルやデータ経路を設定する必要はありません。TCPに比べて高速であるが、信頼性が薄いという特徴があります。

Cによるネットワークプログラミングを理解したい

解決済

回答 3

投稿

  • 評価
  • クリップ 1
  • VIEW 2,191
退会済みユーザー

退会済みユーザー

前提・実現したいこと

下記のC言語によるネットワーク対戦鬼ごっこプログラムを理解したいので, 理解に必要だったり役に立つ書籍やウェブサイトを教えていただきたいです.
私は柴田望洋氏の新明解C言語入門編を終えたばかりで, ネットワークに関する勉強はほとんどしていませんので, 下記のソースコードはほとんど理解できません.
分からない部分を個別で調べてみたりもしたのですが, なにぶん分からないことが多いので書籍などで勉強したいです.

該当のソースコード

#ifndef _GAME_LIB_H_
#define _GAME_LIB_H_

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
#include <sys/time.h>

#define DEFAULT_PORT 6000
#define MAX_MSG 1024
#define STRNCMP(STRING_A,STRING_B)  strncmp(STRING_A, STRING_B, strlen(STRING_B))
#define MIN(a,b) (((a)<(b))?a:b)

typedef enum _Status {
  CONNECTED,
  DISCONNECTED,
} Status;

typedef enum _Control {
  OPEN_SESSION,
  CLOSE_SESSION,
  SESSION_ESTABLISHED,
  COORDINATION,
  GAMEOVER,
  EXCEPTION,
} Control;

typedef struct _Control_Parameter {
  Control control;
  char* parameter;
} Control_parameter;

int socket_and_bind(int myPort);
void get_server_addr(char *hostname, int port, struct sockaddr_in *p_addr);
int send_message(int mySocket, char *buf, struct sockaddr_in *p_addr);
int send_open_session(int mySocket, struct sockaddr_in *p_addr, int lines, int cols);
int send_close_session(int mySocket, struct sockaddr_in *p_addr);
int send_coordinateion(int mySocket, struct sockaddr_in *p_addr, int x, int y);
int send_gameover(int mySocket, struct sockaddr_in *p_addr);
int send_session_established(int mySocket, struct sockaddr_in *p_addr, int lines, int cols);
int receive_message(int mySocket, char *buf, struct sockaddr_in *p_addr);
int sockaddr_in_cmp(struct sockaddr_in *first, struct sockaddr_in *second);
Control_parameter message_interpreter(char* buffer);

#endif /* _GAME_LIB_H_ */
#include "game_lib.h"

int socket_and_bind(int port)
{
  int mySocket;
  struct sockaddr_in myAddr;
  /* ソケット生成 */
  if((mySocket = socket(PF_INET, SOCK_DGRAM, 0)) < 0){
    fprintf(stderr,"Error:socket\n");
    exit(EXIT_FAILURE);
  }
  /* 自身のアドレス構造体設定 */
  bzero((char *)&myAddr, sizeof(myAddr));
  myAddr.sin_family = AF_INET;
  myAddr.sin_addr.s_addr = htonl(INADDR_ANY);/*使用NIC制約なし*/
  myAddr.sin_port = htons(port);/*設定ポート番号*/
  /* アドレス構造体の情報を生成ソケットに関連づけ */
  if(bind(mySocket, (struct sockaddr *)&myAddr, sizeof(myAddr)) < 0){
    fprintf(stderr,"Error:bind\n");
    exit(EXIT_FAILURE);
  }
  return mySocket;
}

void get_server_addr(char *hostname, int port, struct sockaddr_in *p_addr)
{
  struct hostent *pHostent = gethostbyname(hostname);
  if(pHostent==NULL){
    fprintf(stderr,"Error:get_server_addr\n");
    exit(EXIT_FAILURE);    
  } else {
    /* サーバのアドレス構造体の設定 */  
    bzero((char *) p_addr, sizeof(struct sockaddr_in));
    p_addr->sin_family = AF_INET; 
    p_addr->sin_port = htons(port);
    bcopy(pHostent->h_addr,(char*)&(p_addr->sin_addr.s_addr),pHostent->h_length);
  }
}

int send_message(int mySocket, char *buf, struct sockaddr_in *p_addr)
{
  int sent_len = sendto(mySocket, buf, strlen(buf), 0, (struct sockaddr *)p_addr, sizeof(*p_addr));
  if(sent_len==-1){
    fprintf(stderr,"Error:send_message\n");
    exit(EXIT_FAILURE);
  } else {
    return sent_len;
  }
}

int send_open_session(int mySocket, struct sockaddr_in *p_addr, int lines, int cols)
{
  char buffer[MAX_MSG];
  sprintf(buffer,"open_session:%d:%d",lines,cols);
  return send_message(mySocket, buffer, p_addr);
}

int send_close_session(int mySocket, struct sockaddr_in *p_addr)
{
  return send_message(mySocket, "close_session", p_addr);
}

int send_coordinateion(int mySocket, struct sockaddr_in *p_addr, int x, int y)
{
  char buffer[MAX_MSG];
  sprintf(buffer,"coordination:%d:%d", x, y);
  return send_message(mySocket, buffer, p_addr);
}

int send_gameover(int mySocket, struct sockaddr_in *p_addr)
{
  return send_message(mySocket, "gameover", p_addr);  
}

int send_session_established(int mySocket, struct sockaddr_in *p_addr, int lines, int cols)
{
  char buffer[MAX_MSG];
  sprintf(buffer,"session_established:%d:%d",lines,cols);
  return send_message(mySocket, buffer, p_addr);  
}

int receive_message(int mySocket, char *buf, struct sockaddr_in *p_addr)
{
  socklen_t addr_len = sizeof(*p_addr);/*型はintでもOKだが,warningがでるのでsocklen_tとする*/
  int read_len = recvfrom(mySocket, buf, MAX_MSG, 0, (struct sockaddr *)p_addr, &addr_len);
  if(read_len==-1){
    fprintf(stderr,"Error:receive_message\n");
    exit(EXIT_FAILURE);    
  } else {
    buf[read_len] = '\0';    
    return read_len;    
  }
}

int sockaddr_in_cmp(struct sockaddr_in *first,struct sockaddr_in *second)
{
  if(first->sin_port == second->sin_port
     && first->sin_addr.s_addr == second->sin_addr.s_addr){
    return 0;
  } else{
    return 1;
  }
}

Control_parameter message_interpreter(char* buffer)
{
  Control_parameter control_parameter;
  static char parameter[MAX_MSG];
  control_parameter.parameter=parameter;
  if(!STRNCMP(buffer, "open_session")){
    sscanf(buffer, "open_session:%[^\n]", parameter);
    control_parameter.control=OPEN_SESSION;
  } else if(!STRNCMP(buffer, "close_session")){
    control_parameter.control=CLOSE_SESSION;
  } else if(!STRNCMP(buffer, "session_established")){
    sscanf(buffer, "session_established:%[^\n]", parameter);    
    control_parameter.control=SESSION_ESTABLISHED;
  } else if(!STRNCMP(buffer, "coordination")){
    sscanf(buffer, "coordination:%[^\n]", parameter);
    control_parameter.control=COORDINATION;
  } else if(!STRNCMP(buffer, "gameover")){
    control_parameter.control=GAMEOVER;
  } else { 
    control_parameter.control=EXCEPTION;
  }
  return control_parameter;
}

補足情報(言語/FW/ツール等のバージョンなど)

環境はMacOS Xです.

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+2

まずはC言語の基礎はある前提とします。

課題は主に2つあると思います。
一つ目はTCP/IPによるネットワークの基礎の基礎です。
二つ目はOSの提供するAPIに関する知識です。

総じていえることは「C言語上でソケットを使う方法」を学ぶことが必要です。C言語単独では、ほぼコンピュータの中のメモリアクセスに関する単純な機能しかありません。ネットワーク機能を使うとかになると、OSの機能をC言語から呼び出す必要があります。(このインタフェースをAPIといいます)これはOSごとに独自に用意されているのでこの仕様を調べることが要求されます。

なお、ネットワークに関しては詳しい知識は必要ありません。ネットワークといえば中継機器間でのルーティング、スイッチングも重要課題ですが、この問題ではそこを考える必要はありません。このプログラムでは両端末間の通信は正常に行うことができていることを前提としています(IPアドレスまたはドメインが既知であることが必要)。ここでは「ソケット」の使い方だけわかっておけば十分だと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

ネットワークに限らず、Mac(Unix)環境でCを学習するのでしたら、値が張りますが、詳解UNIXプログラミングがいいかと思います(ネットワークのプログラミングについても書かれています)。
さらに突き詰めるようであれば、UNIXネットワークプログラミング〈Vol.1〉UNIXネットワークプログラミング〈Vol.2〉でしょうか。

いずれも大型本ですが、持っていて損はないと思います。

追補:
UNIXネットワークプログラミングですが、店頭では入手困難の模様なので、TCP/IPソケットプログラミングC言語編もおすすめに入れておきます。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

いわゆるバークレーソケットと呼ばれるBSD UNIXでの基本的な通信PGMです。
Mac OSXも、中身はDarwinと呼ばれるUNIXなので、このような方式で通信を行います。WindowsでもWinSockと呼ばれる仕組みで実装しますが、ほとんど同じような形で実現できます。

ソケットプログラミングで検索すると、いろいろ情報が見つかると思います。

現在では直接ソケットを使うようなプログラムを書くことは稀ですが、知っておくにこしたことはない内容だと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

同じタグがついた質問を見る

  • C

    4517questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • MacOS(OSX)

    2353questions

    MacOSとは、Appleの開発していたGUI(グラフィカルユーザーインターフェース)を採用したオペレーションシステム(OS)です。Macintoshと共に、市場に出てGUIの普及に大きく貢献しました。

  • TCP

    187questions

    TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。

  • UDP

    74questions

    UDP(User Datagram Protocol)とは、トランスポート層のプロトコルであり、コネクション型のデータサービスです。IPネットワーク上の別のホストにコンピュータのアプリケーションがメッセージを送ることができ、転送チャンネルやデータ経路を設定する必要はありません。TCPに比べて高速であるが、信頼性が薄いという特徴があります。