Shammer's Philosophy

My private adversaria

EchoServer

そろそろ、実用的かどうかは別にして、これまでよりは大きいプログラムを書いてみようと思う。C言語で EchoServer を書く。C でSocketプログラミングする際の流れとしては、

  1. socket を開く
  2. bind で socket が使用するリスンアドレス、ポートを指定する
  3. listen して待ち受けスタート
  4. accept してクライアント Socket を受け入れ
  5. accept したクライアント Socket に対し、read、write等を使用してデータのやりとりをする
  6. close する

という流れになる。サンプルを書いてみた。こんな感じだろうか。

#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <unistd.h>

int main(int argc, char *args[]) {
    if (argc != 3) {
	printf("Usage: %s $ListenAddress $ListenPort\n", args[0]);
	return 1;
    }
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    int listen_fd;
    int conn_fd;

    int rsize;
    char receive_buffer[1024];

    // Passive Open
    if (( listen_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) {
	perror("socket");
	return 2;
    }

    // 0 clear server_addr structure
    bzero((char *)&server_addr, sizeof(server_addr));

    // Initialize server socket structure and bind server socket
    server_addr.sin_family = PF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(8080);
    if ( bind(listen_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0 ) {
	perror("bind");
	return 3;
    }

    // Port Listen
    if ( listen(listen_fd, SOMAXCONN) < 0 ) {
	perror("listen");
	return 4;
    }
    printf("Start Listening Port : %d...\n", 8080);

    // Accept Client connection request
    unsigned int len = sizeof(client_addr);
    if ( (conn_fd = accept(listen_fd, (struct sockaddr *)&client_addr, &len )) < 0 ) {
	perror("accept");
	return 5;
    }

    // Close Server Socket
    close(listen_fd);

    // Read client data
    do {
	rsize = recv(conn_fd, receive_buffer, 1024, 0);
	if ( rsize == 0 ) {
	    // Disconnect from client
	    break;
	}
	else if ( rsize == -1 ) {
	    perror("recv");
	    return 6;
	}
	else {
	    write(conn_fd, receive_buffer, rsize);
	}
    } while (1);

    // Close Client Socket
    if ( close(conn_fd) < 0 ) {
	perror("close");
	return 7;
    }

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

コンパイル通るのは確認したが、通信できるかは確認していない。ちょっとずつこれを改良していって、本格的にしていきたい。次はクライアント書いてみるか。なお、この実装は[C言語]Socket間通信 echoサーバを作る « イイ!! プログラミング Blogをベースにさせていただきました。