Sockets TCP套接字仅接收消息的一部分
我使用以下代码执行tcp套接字连接并向IP发送字符串。但有时在回复中,我没有收到完整的文件Sockets TCP套接字仅接收消息的一部分,sockets,tcp,Sockets,Tcp,我使用以下代码执行tcp套接字连接并向IP发送字符串。但有时在回复中,我没有收到完整的文件 Socket m_socClient; IPSelected ="1.1.2.3" Port = "80" string query ="My Query" m_socClient = new Socket(AddressFamily.InterNetwork, SocketType.
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=新字节[3000];
有没有办法不硬编码这个数字3000。它大部分时间都在工作,但对于较长的字符串,它只能得到一半的时间。
我希望它能够处理可变大小的消息,而不是将字节大小设置为30000
谢谢阅读。它告诉您如何确定服务器响应的结束,以便您知道要读取多少字节。您必须首先读取并处理服务器的响应头,以便了解剩余数据(如果有的话)是如何传输的。然后,您可以相应地继续从套接字读取,潜在地解析您所读取的内容,直到实际到达响应的末尾。您当前的阅读代码甚至无法满足该要求
例如(伪代码):
line=读取CRLF分隔行;
responseNum=从行中提取;
httpVer=从生产线提取;
做
{
行=读取CRLF分隔行;
如果(行==“”)中断;
将行添加到标题列表中;
}
虽然(正确);
如果((响应数/100)!=1)&&
(responseNum!=204)&&
(响应数!=304)&&
(请求不是“头”))
{
if((标题具有“传输编码”)&&
(标题[“传输编码”]!=“标识”))
{
做
{
行=读取CRLF分隔行;
chunkLen=从行中提取,解码十六进制值;
如果(chunkLen==0)中断;
准确读取chunkLen字节数;
读取并丢弃CRLF分隔行;
}
虽然(正确);
做
{
行=读取CRLF分隔行;
如果(行==“”)中断;
将行添加到标题列表,如果存在,则覆盖;
}
虽然(正确);
如果不仅仅是“分块”,则基于头[“传输编码”]值解码/转换读取数据
}
else if(标题具有“内容长度”)
{
准确读取标题[“内容长度”]字节数
}
else if(标题[“内容类型”]==多部分/byteranges)
{
边界=标题[“内容类型”][“边界”];
读取并解析MIME编码数据,直到到达“-”+边界+“--”行;
}
其他的
{
阅读直到断开;
}
}
如果(((httpVer>=1.1)和&(头[“连接”]=“关闭))||
((httpVer<1.1)和&(标题[“连接”!=“保持活动”))
{
断开
}
我把它留作一个练习,让您在代码中实际实现它。读取。它告诉您如何确定服务器响应的结尾,以便您知道要读取多少字节。您必须首先读取并处理服务器的响应头,以便知道剩余数据(如果有)是如何传输的。然后您可以继续重新读取相应地从套接字读取,可能解析您所读取的内容,直到实际到达响应的末尾。您当前的读取代码甚至无法满足该要求
例如(伪代码):
line=读取CRLF分隔行;
responseNum=从行中提取;
httpVer=从生产线提取;
做
{
行=读取CRLF分隔行;
如果(行==“”)中断;
将行添加到标题列表中;
}
虽然(正确);
如果((响应数/100)!=1)&&
(responseNum!=204)&&
(响应数!=304)&&
(请求不是“头”))
{
if((标题具有“传输编码”)&&
(标题[“传输编码”]!=“标识”))
{
做
{
行=读取CRLF分隔行;
chunkLen=从行中提取,解码十六进制值;
如果(chunkLen==0)中断;
准确读取chunkLen字节数;
读取并丢弃CRLF分隔行;
}
虽然(正确);
做
{
行=读取CRLF分隔行;
如果(行==“”)中断;
将行添加到标题列表,如果存在,则覆盖;
}
虽然(正确);
如果不仅仅是“分块”,则基于头[“传输编码”]值解码/转换读取数据
}
else if(标题具有“内容长度”)
{
准确读取标题[“内容长度”]字节数
}
else if(标题[“内容类型”]==多部分/byteranges)
{
边界=标题[“内容类型”][“边界”];
读取并解析MIME编码数据,直到到达“-”+边界+“--”行;
}
其他的
{
阅读直到断开;
}
}
如果(((httpVer>=1.1)和&(头[“连接”]=“关闭))||
((httpVer<1.1)和&(标题[“连接”!=“保持活动”))
{
断开
}
我把它留作练习,让您在代码中实际实现它。读取套接字的代码在哪里?您必须一直读取,直到服务器关闭连接,或者您已收到最后一个数据块,或者读取内容长度标题指示的字节,或者。。。使用诸如WebClient或HttpClient之类的HTTP库。我无权访问服务器代码。我确信他们收到了全部的信息。因为直到他们收到一个完整的字符串并通过验证,他们才用另一个字符串响应。问题不在于阅读。接收响应时会出现问题,如@CodeCaster所说-从套接字读入bytesReceived数组的代码在哪里?@MartinJames:oops抱歉。。我不小心拆下了那条线。为什么不使用URL和URLConnection?他们解决了所有这些问题,还有很多其他问题。读取套接字的代码在哪里?您必须一直读取,直到服务器关闭连接,或者您已收到最后一个数据块,或者读取内容长度标题指示的字节,或者。。。使用HTTP库,如WebClient或HttpClient。我没有访问HTTP库的权限
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;
}