HttpClient访问套接字应用程序

4
我最初使用HttpClient作为REST服务的访问路径,但后来发现它是运行在端口80上的JSON服务,实际上是一个套接字应用程序。HttpClient打开了远程端口,但当它发送JSON请求时却从未收到响应。我曾经努力让Fiddler返回响应,但却一直失败。但我成功地通过wget和curl发送/接收了响应,于是我找到原始开发人员,他提到这不是真正的“REST”服务,而只是一个发送/接收JSON数据的套接字应用程序。我是否可以调整HttpClient以便访问套接字应用程序,还是需要退回并使用WebSockets?以下是发送/接收JSON包的测试代码。
        private async Task ProcessZone(string szIPAddress)
    {
        string responseData = string.Empty;

        Uri baseAddress = new Uri(@"http://" + szIPAddress + "/player");

        try
        {
            using (var httpClient = new HttpClient { BaseAddress = baseAddress })
            {
                var _req = new SendRequest();
                _req.id = "rec-100";
                _req.url = "/stable/av/";
                _req.method = "browse";

                var _json = JsonConvert.SerializeObject(_req);

                using (var content = new StringContent(_json,Encoding.UTF8, "application/json"))
                {
                    using (var response = await httpClient.PostAsync(baseAddress, content))
                    {
                        responseData = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
                    }
                }
            }

            var _Response = JsonConvert.DeserializeObject<Response>(responseData);

            var item = new ZoneInfo();
            item.szIPAddress = szIPAddress;
            item.szZoneName = _Response.result.item.title;
            lstZones.Add(item);

        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message);
        }
    }

    private async Task ProcessZones()
    {

        foreach (var item in ZoneSearch)
        {
            await ProcessZone(item.IPAddress);
        }
    }

连接卡在此行:
using (var response = await httpClient.PostAsync(baseAddress, content))

我应该提到,上面的代码在真正的REST服务中可以正常工作...


调用ProcessZone()的代码是否“正确”的异步/等待(一直到最上层),或者堆栈中更高层次的代码调用了.Result()或.Wait()? - sellotape
是的,当访问真实的REST服务时,一切都正常工作。但我猜我试图访问的不是REST服务,而是在套接字上运行的JSON服务。需要打开连接,调用JSON并接收响应,然后关闭连接。不过我会编辑以包括调用函数。 - Zonus
无论如何,你都应该像第二个一样,在第一个await中添加.ConfigureAwait(false)。如果堆栈中的更高级别的代码调用了.Result()或.Wait(),没有它可能会导致死锁。 - sellotape
此外,REST本身并不涉及此事,但服务实现HTTP协议的程度和方式可能会影响。 - sellotape
这也是我所想的... - Zonus
显示剩余2条评论
1个回答

6
那时我与原开发者交谈,他提到这并不是真正的“REST”服务,而只是一个发送/接收JSON的套接字应用程序。
了解协议是制作工作客户端的第一步。
很遗憾,既不能调整HttpClient以访问套接字应用程序,也不能退回使用WebSockets。正如其名称所示,HttpClient仅适用于HTTP服务。由于服务器不是HTTP服务器,因此无法使用HttpClient。WebSockets具有相当令人困惑的名称,因为它们不是原始套接字,而是使用WebSocket协议,该协议需要进行HTTP握手来建立连接。由于服务器不是HTTP/WebSocket服务器,因此无法使用WebSockets。
您唯一的选择是要么向开发人员施加压力编写真正的REST服务(这将使您的工作容易得多),要么使用原始套接字(例如Socket)。正确地使用原始套接字非常困难,因此我建议您向开发人员施加压力编写像今天世界上其他人一样的REST服务。

1
谢谢,这就是我需要知道的。我同意,编写REST接口要容易得多。但我也有使用套接字的经验。虽然我必须自己编写线程,这可能不会像REST一样愉快,但这是我必须做的。我认为我不太可能成功地说服他重新编写为REST;可悲的是这个服务是在Linux上运行的C++服务,所以这将是一项相当费力的工作,而且对他没有任何激励。 :( - Zonus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接