Shammer's Philosophy

My private adversaria

EchoServerV4

EchoServerV4_alpha - Shammerismの実装を少し修正。accept の位置を変更。それから、サーバー側の Socket をクローズする箇所も想定通りの動作をさせるためには不適切だったのでこれも変更した。Version 4 の実装は以下。

#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);

	// Read client data
	do {
	    // 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;
	    }

	    rsize = recv(conn_fd, receive_buffer, 1024, 0);
	    if ( rsize == 0 ) {
		// Disconnect from client
		printf("Client closed...\n");
	    }
	    else if ( rsize == -1 ) {
		perror("recv");
		return 6;
	    }
	    else {
		printf("Received Message:%s\n", receive_buffer);
		write(conn_fd, receive_buffer, rsize);
		if( strcmp( receive_buffer, "quit") == 0 ){
		    write(conn_fd, "EchoServer quit.\n", strlen("EchoServer quit.\n"));
		    break;
		}
	    }
	} while (1);

	// Close Server Socket
	close(listen_fd);

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

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

動作確認結果は以下。

$ ./eserver 10080
Start Listening Port : 10080...
Received Message:Test
Received Message:Test
Received Message:Quit
Received Message:quit
Connection closed.
$

期待通りっぽい。しかし、クライアント側でサーバーからの応答を表示するようになっていないので、今度はクライアントを書き換えて、サーバーから受け取ったメッセージを表示するようにしようと思う。クライアントでは名前解決して、ホスト名で接続できるようにもしたい。

$ ./eclient 127.0.0.1 10080 Test
$ ./eclient 127.0.0.1 10080 Test
$ ./eclient 127.0.0.1 10080 Test
$ ./eclient 127.0.0.1 10080 Test
$ ./eclient 127.0.0.1 10080 Test
$ ./eclient 127.0.0.1 10080 Quit
$ ./eclient 127.0.0.1 10080 quit
$