Shammer's Philosophy

My private adversaria

EchoServerV3

EchoServerV2 - Shammerismの EchoServer を動作させて、クライアントからメッセージ送ってみたけれども、受け取ったメッセージを表示させない作りになっていたので表示させるようにちょっとだけ書き換えました。

// http://d.hatena.ne.jp/shammer/20090730

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

int checknumber(char *v){
    int len = strlen(v);
    int i;
    int result = 1;
    for(i = 0; i < len && result ; i++){
	result = isdigit(v[i]);
    }
    return result;
}

int main(int argc, char *args[]) {
    if (argc != 2) {
	printf("Usage: %s $ListenPort\n", args[0]);
	return 1;
    }
    if ( checknumber(args[1]) ){    
	struct sockaddr_in server_addr;
	struct sockaddr_in client_addr;
	int port = atoi(args[1]);
	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(port);
	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", port);

	// 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 {
		printf("Received Message:%s\n", receive_buffer);
		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;
    }
}

「printf("Received Message:%s\n", receive_buffer);」の行を追加しただけ。

C で文字列を扱う際には、予め適当なサイズを確保しておかないといけないのが気になる。使用するかしないかわからない、バッファを確保しておかなくてもいい書き方はないものかと思うのだが、おそらくこれはいたし方ないんだろうとも思う。この点をうまくやる書き方があるのであれば、それも取り入れたいと思うが、バッファの解決策がないとしても、

  • 単発で終わらない
  • 特定の文字列を受け取った際に終了する
  • マルチスレッド化

という点は拡張したい。