【问题标题】:TCP Socket receiving only a part of the messageTCP Socket 只接收部分消息
【发布时间】:2014-01-24 11:59:28
【问题描述】:

我正在使用以下代码执行 tcp 套接字连接并将字符串发送到 IP。但有时在响应中,我没有收到整个文件

     Socket m_socClient;
        IPSelected ="1.1.2.3"
                Port = "80"
                string query ="My Query"
                m_socClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                System.Net.IPAddress remoteIPAddress = System.Net.IPAddress.Parse(IPSelected);
                System.Net.IPEndPoint remoteEndPoint = new System.Net.IPEndPoint(remoteIPAddress, Port);
                m_socClient.Connect(remoteEndPoint);
                try
                {
                    if (m_socClient.Connected)
                    {                       
                        var reQuestToSend = "";


                            reQuestToSend = string.Format("POST /TMHP/Request HTTP/1.1\r\nHost:{0}\r\nContent-Length:{1}\r\n\r\n{2}", "edi-webtest.tmhp.com", Query270.Length, Query270);
                        byte[] bytesToSend = Encoding.ASCII.GetBytes(reQuestToSend);
                        byteCount = m_socClient.Send(bytesToSend, SocketFlags.None);
                        byte[] bytesReceived = new byte[3000];
  byteCount = m_socClient.Receive(bytesReceived, SocketFlags.None);
                        Response271 = Encoding.ASCII.GetString(bytesReceived);

                    }
                }
                catch (Exception ex)
                {
                    EVCommon.Log(ex.Message);

                }
                finally
                {
                    m_socClient.Disconnect(false);
                    m_socClient.Close(5000);
                }

我认为问题出在 byte[] bytesReceived = new byte[3000]; 有没有办法不对这个数字 3000 进行硬编码。它大部分时间都有效,但对于较长的字符串,它只能得到一半。 我希望它处理可变大小的消息,而不是将字节大小设置为 30000 谢谢

【问题讨论】:

  • 读取socket的代码在哪里?您必须继续阅读,直到服务器关闭连接,或者您收到最后一个块,或者读取 Content-length 标头指示的字节,或者......使用 WebClient 或 HttpClient 之类的 HTTP 库。跨度>
  • 我无权访问服务器代码。我确信他们会收到整个字符串。因为在他们收到一个完整的字符串并最终通过验证之前,他们不会用另一个字符串响应。问题不在于阅读。这是接收响应的问题
  • 就像@CodeCaster 所说 - 从套接字读取到 bytesReceived 数组的代码在哪里?
  • @MartinJames:哎呀对不起..我不小心删除了那条线。编辑后的帖子
  • 你为什么不使用 URL 和 URLConnection 呢?他们解决了所有这些问题,以及许多其他问题。

标签: sockets tcp


【解决方案1】:

阅读RFC 2616 Section 4.4。它告诉您如何确定服务器响应的结束,以便您知道要读取多少字节。您必须首先读取并处理服务器的响应标头,以便了解剩余数据(如果有)是如何传输的。然后您可以相应地继续从套接字读取,可能会解析您已读取的内容,直到实际到达响应的末尾。您当前的阅读代码甚至无法满足该要求。

例如(伪代码):

line = read a CRLF-delimited line;

responseNum = extract from line;
httpVer = extract from line;

do
{
    line = read a CRLF-delimited line;
    if (line == "") break;
    add line to headers list;
}
while (true);

if (((responseNum / 100) != 1) &&
    (responseNum != 204) &&
    (responseNum != 304) &&
    (request was not "HEAD"))
{
    if ((headers has "Transfer-Encoding") &&
        (headers["Transfer-Encoding"] != "identity"))
    {
        do
        {
            line = read a CRLF-delimited line;
            chunkLen = extract from line, decode hex value;
            if (chunkLen == 0) break;
            read exactly chunkLen number of bytes;
            read and discard a CRLF-delimited line;
        }
        while (true);

        do
        {
            line = read a CRLF-delimited line;
            if (line == "") break;
            add line to headers list, overwrite if exists;
        }
        while (true);

        decode/transform read data based on headers["Transfer-Encoding"] values if more than just "chunked"
    }
    else if (headers has "Content-Length")
    {
        read exactly headers["Content-Length"] number of bytes
    }
    else if (headers["Content-Type"] == multipart/byteranges)
    {
        boundary = headers["Content-Type"]["boundary"];
        read and parse MIME encoded data until "--"+boundary+"--" line is reached;
    }
    else
    {
        read until disconnected;
    }
}

if (((httpVer >= 1.1) && (headers["Connection"] == "close)) ||
    ((httpVer < 1.1) && (headers["Connection"] != "keep-alive")))
{
    disconnect;
}

我把它作为练习留给你在你的代码中实际实现它。

【讨论】:

  • 你有个例子。您已收到您尝试发送的请求,以及您尝试阅读的响应。
  • 我可以尝试实现它。但是在每天 500 或 1000 笔交易中,我在不到 5 个请求中就遇到了这个问题。所以 95% 或更多是成功的。
  • 但是即使您显示的代码也存在基本问题。到目前为止,你很幸运,它完全可以工作,更不用说 95% 的时间了。您没有格式化/发送请求应该如何处理,并且您必须实现我概述的算法才能正确获得响应。这就是 HTTP 的工作原理。您确实应该使用预制的 HTTP API/库,而不是尝试手动实现 HTTP。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-16
  • 1970-01-01
  • 1970-01-01
  • 2019-11-08
  • 2013-12-26
  • 1970-01-01
相关资源
最近更新 更多