读取期间通过套接字连接超时获取请求

Get request via socket connect timing out during read

我正在尝试用 OCaml 编写一个 http 客户端:

module Connection = struct
    let sock_fd =
        let s_fd = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in
        Unix.setsockopt s_fd Unix.TCP_NODELAY true;
        s_fd

    let read_from_sock () =
        let buffer = Bytes.create 512 in
        let rec read_all request buffer =
            let r = Unix.read sock_fd buffer 0 512 in
            if r < 512 then request ^ buffer
            else read_all (request ^ buffer) buffer in
        read_all "" buffer

    let write_to_sock str =
        let len = String.length str in
        let _ = Unix.write sock_fd str 0 len in ()

    let make_request request serv_addr =
        Unix.connect sock_fd serv_addr;
        write_to_sock request

    class connection address port =
        object
            val serv_addr = Unix.ADDR_INET (Unix.inet_addr_of_string address, port)

            method get_response request =
                let _ = make_request request serv_addr in
                let rec wait_for_response () =
                    let response = read_from_sock () in
                    match String.length response with
                    | 0 -> wait_for_response ()
                    | _ -> Printf.printf "%s\n" response in
                wait_for_response ();
                Unix.shutdown sock_fd Unix.SHUTDOWN_ALL;
                Unix.close sock_fd
        end

    let create address port = new connection address port
end

let connection = Connection.create "54.175.219.8" 80;;
connection#get_response "GET / HTTP/1.1\r\n"

程序只是挂起,直到在读取期间重置连接时崩溃。时髦的部分是,没有抛出其他错误。由于 OCaml 不像 C 那样 return int 响应,我会假设如果我在连接或创建套接字时做错了什么,运行时会抛出错误。

如果您不熟悉 OCaml,我假设我正在做的(非常粗糙的)伪 C 等价物是这样的(也许这将有助于调试):

int sock_fd = socket(PF_INET, SOCK_STREAM);
setsockopt(sock_fd, TCP_NODELAY, 1);

serv_addr addr {"54.175.219.8", 80};
connect(sock_fd, &serv_addr);
write(sock_fd, "GET / HTTP/1.1\r\n");

char buffer[512];
while (buffer = read(sock_fd)) {
    printf("%s\n", buffer);
}

shutdown(sock_fd, SHUTDOWN_ALL);
close(sock_fd);

如果这没有帮助,请忽略它。我只是想我会用伪代码进行总结。有什么突出的问题吗? (除了不读取 C 中 socket/connect/write 的 int 响应之外,因为 OCaml 的运行时应该注意这里抛出的错误。)

HTTP 中,协议请求应该以两行空行结束,而不是一行(通俗地说)。在你的例子中,服务器只等待第二个 "enter",你的客户端阻塞直到它收到响应。只需在您的请求中添加额外的 \r\n,一切都会正常进行……更好。至少你会得到回应。但是您的代码包含一些小故障,因此请预料到会出现问题。

仅供参考,OCaml 中有许多用于网络的优秀库。我认为最好的是 cohttp. Also, you may find interesting mine socket library,它比 cohttp

低一点