エラー処理

 今回はエコーサーバのエラー処理機能を作成します。
 ソフトウェアの開発のデバックやサーバの構築の現場では、トラブル解決の手段としてログを頻繁に利用します。そのためエラー発生時には、できるだけ詳細にエラーの内容を表示できるようにするべきです。

 例えば現在のエコーサーバは、サーバのプロセスを二重に起動しても、エラーは表示されません。しかし、エコーサーバがlistenするポートは一つしかないので、当然エラーとして通知されるべきです。

 実際には、失敗時だけでなく成功時もログにメッセージが表示されると、エラー発生時の問題の切り分けが容易になります。ただそうなるとログの表示が冗長になりすぎ、ログの可読性が低下します。そのためには、プログラム開始時にログレベルを指定して、どこまでログとして記録するかを選択できるようにするのが望ましいです。

エラー処理の対象

 以下の
1. sock関数でのソケットの作成
2. bind関数でのソケットの命名
3. listen関数でのクライアントからの接続待ち受け準備
4. accept関数でのクライアントからの接続
5.closeでソケットを閉じる
それぞれのタイミングでエラー処理を行います。

ソースコード

1. sock関数でのソケットの作成

int sockfd;
sockfd = socket(AF_INET,SOCK_STREAM,0);

if( sockfd == -1 ){
       syslog(LOG_CRIT,"failed to create socket");
}else{
       syslog(LOG_INFO,"created new socket...%d",sockfd);
}

2. bind関数でのソケットの命名

struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(10000);
server.sin_addr.s_addr = INADDR_ANY;

if(bind(sockfd,(struct sockaddr *)& server,sizeof(struct sockaddr)) == -1){
        syslog(LOG_CRIT,"failed to bind socket.");
}else{
        syslog(LOG_INFO,"socket %d was binded.",sockfd);
}

3. listen関数でのソケットのクライアントからの待ち受け準備

if(listen(sockfd,5) == -1){
        syslog(LOG_CRIT,"failed to listen socket...%d.",sockfd);
}else{
        syslog(LOG_INFO,"socket...%d was listened.",sockfd);
}

4. accept関数でのソケットのクライアントからの接続

int sockfd;
struct sockaddr_in client;
int len = sizeof(struct sockaddr_in);

sockfd = accept(sock, (struct sockaddr *) &client, &len);
if( sockfd == -1){
        syslog(LOG_CRIT,"failed to accept sock...%d",sock);
}else{
        syslog(LOG_INFO,"accepted sock...%d",sock);
}

5. close関数でのソケットのクローズ

if( close(sock) == -1){
        syslog(LOG_CRIT,"failed to close socket...%d",sock);
}else{
        syslog(LOG_INFO,"socket...%d was closed.",sock);
}