ChatGPTに実験課題をやらせてみる

この記事はISer Advent Calendar 2022の7日目として書かれました。

adventar.org

この記事では昨今話題のChatGPTに弊学科の課題は解くことができるのか検証していこうと思います。さすがに現在進行形で課されているものを解いてもらうのはいろいろと問題があるので、過去に出された課題を解いてもらうことにします。今回は多くのISerが苦戦した(そしてこれからも苦戦すると思われる)C言語でのTCP通信の実装(シスプロ第4回)をやらせてみることにします。

まずは問題の要件を明文化してChatGPTに与えます。

文字数制限があるので途中で出力が途切れてしまうのが問題ですね。ただ単に「続きを見せてください」と言ったらトンチンカンなことを言ってきたので、具体的に「○○より先」と指定する必要がありそうです。

結果として出力されたserver.cはこのようになりました。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

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

#define MAX_LINE 100

int main(int argc, char* argv[]) {
    // コマンドライン引数に指定されたポート番号を変数 port に保存
    int port = atoi(argv[1]);

    // ストリーム型 (TCP) のソケットを作成
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);

    // sockaddr_in 構造体を定義し、ポート番号とアドレスファミリを設定
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = INADDR_ANY;

    // ソケットを特定のポートにバインド
    bind(sockfd, (struct sockaddr*) &addr, sizeof(addr));

    // ソケットを待ち受け状態にする (最大 5 接続まで対応)
    listen(sockfd, 5);

    // 接続要求を受け付けるためのソケットを定義
    int client_sockfd;

    // 接続されたクライアントの情報を保存する sockaddr_in 構造体
    struct sockaddr_in client_addr;
    socklen_t len = sizeof(client_addr);

    // クライアントからの接続を受け付ける
    client_sockfd = accept(sockfd, (struct sockaddr*) &client_addr, &len);

    // クライアントから受信したデータを格納する配列
    char buf[MAX_LINE];

    // 無限ループ (Ctrl + C でプログラムを終了させる)
    while (1) {
        // クライアントからのデータを受信
        int n = recv(client_sockfd, buf, MAX_LINE, 0);

        // 受信したデータを標準出力へ出力
        printf("Received: %s", buf);

        // 受信したデータをクライアントに送信
        send(client_sockfd, buf, n, 0);

        // 受信したデータが "END" の場合は通信を終了し、接続要求を再度受け付ける
        if (strncmp(buf, "END", 3) == 0) {
            close(client_sockfd);
            break;
        }
    }

    // ソケットをクローズ
    close(sockfd);

    return 0;
}

パッと見た感じきちんとプログラムとして成立していそうです。コードコメントも私が書くのよりよほど丁寧で読みやすい。「最大 5 接続まで対応」「受信したデータが "END" の場合は通信を終了」などとちょいちょい余計な仕様を足されているのが気にかかりますが。

client.cも出力してもらうこととしましょう。

こちらはプログラムは割愛しますが、大体server.cと似たような感じで書けています。

gccコンパイルしてWSL上で実行してみます。この辺の画像細かくて見づらいですねごめんなさい。

無事に実行できました。コマンドライン引数などの仕様もきちんと満たしています。

複数のクライアントとの通信も試してみます。

この画像からだと何も分かりませんが、2つ目のクライアントから文字列を送っても最初反応はなく、なぜか1つ目のクライアントが終了すると同時に返ってきました。このときにサーバも終了してしまったので、この辺りはまだ課題がありそうです。

あらためて要件を満たすように書き直してもらうこととします。

新しく出力されたserver.cをコンパイルして実行すると、今度はきちんと複数クライアントとの通信を行うことができました。もう何も言うことはありません。

ご丁寧に実行方法まで教えてくれます。もう猫でもISerになれる時代になってしまいました。

結論

ChatGPTは我々が苦戦した課題をいとも簡単に解いてしまうことができると分かりました。正直ここまでとは思っていなくて驚いています。このようなものが無料で公開された以上、そろそろ実験や課題のあり方を考え直すべきなのかもしれません。