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

int main() {
    int sockfd;
    int client_sockfd;
    struct sockaddr_in addr;
    fd_set rfds;
    int i;

    socklen_t len = sizeof( struct sockaddr_in );
    struct sockaddr_in from_addr;

    char buf[1024];

    // 受信バッファ初期化
    memset( buf, 0, sizeof( buf ) );

    // ソケット生成
    if( ( sockfd = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 ) {
        perror( "socket" );
    }

    // 待ち受け用IP・ポート番号設定
    addr.sin_family = AF_INET;
    addr.sin_port = htons( 1234 );
    addr.sin_addr.s_addr = INADDR_ANY;

    // バインド
    if( bind( sockfd, (struct sockaddr *)&addr, sizeof( addr ) ) < 0 ) {
        perror( "bind" );
    }

    // 接続要求待ち
    if( listen( sockfd, 10 ) < 0 ) {
        perror( "listen" );
    }

    // クライアントからの接続受け入れ
    if( ( client_sockfd = accept( sockfd, (struct sockaddr *)&from_addr, &len ) ) < 0 ) {
        perror( "accept" );
    }

    // 受信
    int rsize;
    while( 1 ) {
        FD_ZERO(&rfds);
        FD_SET(client_sockfd, &rfds);
        if (select((client_sockfd + 1), &rfds, NULL, NULL, NULL) < 1) {
                perror( "select" );
        }

        rsize = recv( client_sockfd, buf, sizeof( buf ), 0 );

        if ( rsize == 0 ) {
            sleep( 10 );
            continue;
        } else if ( rsize == -1 ) {
            perror( "recv" );
        } else {
            printf( "receive(%d):%02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x\n", rsize,
                 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],
                 buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]);
            sleep( 1 );

            // data update
            for (i = 0 ; i < rsize ; i++)
            {
                buf[i] += 0x10;
            }

            // 応答
            printf( "send:%s\n", buf );
            write( client_sockfd, buf, rsize );
        }
    }

    // ソケットクローズ
    close( client_sockfd );
    close( sockfd );
    return 0;
}
