// 第一课：最简单的阻塞 echo server，一次只能服务一个客户端
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cstdio>
#include <cstring>

int main() {
    // 1. socket：向系统要一个“插座”（文件描述符 fd）
    int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
    int opt = 1;
    setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    // 2. bind：把插座绑定到 本机任意IP:8888
    sockaddr_in addr{};
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    addr.sin_port = htons(8888);
    if (bind(listen_fd, (sockaddr*)&addr, sizeof(addr)) < 0) { perror("bind"); return 1; }

    // 3. listen：开始营业，等客人上门
    listen(listen_fd, 128);
    printf("listening on 8888\n");

    while (true) {
        // 4. accept：接待一个客人，拿到和他专属的 conn_fd（没人来就一直卡在这）
        int conn_fd = accept(listen_fd, nullptr, nullptr);
        printf("new client fd=%d\n", conn_fd);

        char buf[1024];
        while (true) {
            // 5. read：等客人说话（不说话就一直卡在这）
            ssize_t n = read(conn_fd, buf, sizeof(buf));
            if (n <= 0) break;            // 0 = 客人挂断，<0 = 出错
            write(conn_fd, buf, n);       // 6. write：原样说回去
        }
        close(conn_fd);
        printf("client fd=%d closed\n", conn_fd);
    }
}
