读取期间通过套接字连接超时获取请求
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
低一点
我正在尝试用 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