gpt4 book ai didi

erlang - 如何使用 gen_tcp :recv correctly

转载 作者:行者123 更新时间:2023-12-04 06:02:24 27 4
gpt4 key购买 nike

我写了一个简单的http客户端,遇到以下问题,我复制粘贴了do_recv来自官方文档,但它的工作方式很奇怪:

do_recv(Sock, Bs) ->
case gen_tcp:recv(Sock, 0, ?TIMEOUT) of
{ok, B} ->
gen_tcp:shutdown(Sock, write), % <-- this appears to fix the problem!
do_recv(Sock, [Bs, B]);
{error, closed} ->
{ok, list_to_binary(Bs)}
end.

聊天顺序如下:
{ok, S} = gen_tcp:connect(Ip, Port, [inet, binary,
{packet, 0},
{active, false},
{nodelay, true},
{reuseaddr, true}], 2000),
Req = io_lib:format("GET ~s HTTP/1.1\r\nHost: ~s\r\n\r\n", [Url, UrlHost]),
ok = gen_tcp:send(S, list_to_binary(Req)) of
do_recv(S, []);

最后调用 do_recv有时按预期工作并返回服务器
respose,但有时它会挂起和超时,我猜是因为服务器没有关闭套接字
在其自己的。
所以第二种超时情况是我想避免的,任何想法
如何应对这种行为?

更新:

我加 gen_tcp:shutdown调用 do_recv函数(参见代码示例中的注释),
这似乎解决了这个问题。我知道这个问题很幼稚,还有解决方案
很像猜测,也许有人仍然可以解释这里发生的事情
他们通常如何解决此类问题。

最佳答案

您的代码有一些问题。

如果您收到 0,您可以获得 GET 字符串的一半,或者您可以获得超过整个 GET 字符串的数量,这取决于内核如何处理流。 TCP 是面向流的,因此您需要从套接字中获取数据,直到获得足够的数据。此外,您很容易以 {error, timeout} 触发结束,因此您也必须处理该问题。否则它不会按预期工作。基本上,您需要一个循环来收集数据,直到您有足够的数据来解析 GET。在您拥有所有数据之前,该循环中将发生超时。

类似的东西:

do_recv(Sock, Gathered) ->
case gen_tcp:recv(Sock, 0, ?TIMEOUT) of
{ok, Bin} ->
Remaining = try_decode(Sock, <<Gathered/binary, Bin/binary>>),
do_recv(Sock, Remaining);
{error, timeout} ->
do_recv(Sock, Remaining);
{error, Reason} ->
exit(Reason)
end.

try_decode(Sock, Gathered) ->
case decode(Gathered) of
{ok, Data, Rest} ->
processor ! Data,
try_decode(Sock, Rest);
need_more_data ->
do_recv(Sock, Gathered)
end.

这里假设几件事
  • decode/1 是一个尝试解码数据的函数,它可能会失败并请求更多数据。
  • 处理器是一个进程,一旦我们解码了某些东西,我们就可以将消息发送到该进程。这也可能是对我们刚刚解码的数据执行某些操作的函数调用。
  • 关于erlang - 如何使用 gen_tcp :recv correctly,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8785478/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com