[C言語]Socket間通信 echoサーバを作る



ネットワークを通して、データをやりとりするためには、Socketに対して、読み書きをします。
C言語による、Socket間通信は、下記のような手順になります。

  1. socket() によりソケットを開く
  2. bind() により、コネクションを受けつけるIPアドレス・ポート番号と ソケットとを対応づける
  3. listen() によりクライアントからの接続待ち受け状態にする
  4. accept() によりクライアントからの接続を受け付ける
  5. read(), write(), send(), recv() などを用いて通信を行う
  6. close() によりソケットを閉じる

実際に文字列を単純にクライアントに返すだけのプログラム(echoサーバ)を書いて見ます。
ちなみに、本コードでは、1回やりとりが終わると、サーバプロセスも終了します。

#include <stdio.h>
#include <stdlib.h>     /* exit() */
#include <string.h>     /* bzero() */
#include <sys/types.h>
#include <sys/socket.h> /* socket(), bind(), listen(), accept(), recv() */
#include <netinet/in.h> /* htons() */
#include <unistd.h>

#define PORT    8823    /* Listenするポート */
#define MAXDATA 1024    /* 受信バッファサイズ */

int main(void)
{
    struct sockaddr_in saddr; /* サーバ用アドレス格納構造体 */
    struct sockaddr_in caddr; /* クライアント用アドレス格納構造体 */

    int listen_fd;
    int conn_fd;

    int len = sizeof(struct sockaddr_in);

    int rsize;
    char buf[MAXDATA]; /* 受信バッファ */

    /* ソケットの生成 */
    if ((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("socket");
        exit(EXIT_FAILURE);
    }

    /* 
      * saddrの中身を0にしておかないと、bind()でエラーが起こることがある
     */
    bzero((char *)&saddr, sizeof(saddr));

    /* ソケットにアドレスとポートを結びつける */
    saddr.sin_family        = PF_INET;
    saddr.sin_addr.s_addr   = INADDR_ANY;
    saddr.sin_port          = htons(PORT);
    if (bind(listen_fd, (struct sockaddr *)&saddr, len) < 0) {
        perror("bind");
        exit(EXIT_FAILURE);
    }

    /* ポートをListenする */
    if (listen(listen_fd, SOMAXCONN) < 0) {
        perror("listen");
        exit(EXIT_FAILURE);
    }
    printf("Start Listening Port : %d...\n", PORT);

 /* 接続要求を受け付ける */
    if ((conn_fd = accept(listen_fd, (struct sockaddr *)&caddr, &len)) < 0) {
        perror("accept");
        exit(EXIT_FAILURE);
    }

    /* Listeningソケットを閉じる */
    close(listen_fd);

    /* 送信されたデータの読み出し */
    do {
        rsize = recv(conn_fd, buf, MAXDATA, 0);

        if (rsize == 0) { /* クラアイントが接続を切ったとき */
                break;
        } else if (rsize == -1) {
                perror("recv");
                exit(EXIT_FAILURE);
        } else {
                write(conn_fd, buf, rsize);
        }
    } while (1);

    if ( close(conn_fd) < 0) {
        perror("close");
        exit(EXIT_FAILURE);
    }

    printf("Connection closed.\n");
    return 0;
}

実行方法

# gcc echoserver.c -o echoserver
# ./echoserver

別のターミナルで

# telnet localhost 8823
# (適当に文字を打ってみる)
# Ctrl-] //入力終了
telnet> quit //接続切断

参考URL

参考書籍

Linux教科書 LPICレベル1 第4版 (CD-ROM付)
Linux教科書 LPICレベル1
¥ 3,990
UNIXネットワークプログラミング入門
UNIXネットワーク
プログラミング入門
TCP/IPソケットプログラミング C言語編
TCP/IPソケット
プログラミング C言語編
¥ 175より

Comments are closed.