I'm using a local server in a Windows Store App (http://blog.jsolutions.co.uk/?p=492) for serve html files.
The program reads the input from socket:
StringBuilder inputRequestBuilder = new StringBuilder();
// Read all the request data.
// (This is assuming it is all text data of course)
using (var input = socket.InputStream)
{
var data = new Windows.Storage.Streams.Buffer(BUFFER_SIZE);
uint dataRead = BUFFER_SIZE;
while (dataRead == BUFFER_SIZE)
{
await input.ReadAsync(data, BUFFER_SIZE, InputStreamOptions.Partial);
var dataArray = data.ToArray();
var dataString = Encoding.UTF8.GetString(dataArray, 0, dataArray.Length);
inputRequestBuilder.Append(dataString);
dataRead = data.Length;
}
}
But sometimes, when the user submit a html form, the inputRequestBuilder has not all the content, for example:
"POST /LMS/ajax.php?op=commitSCORM HTTP/1.1\r\nAccept: */*\r\nContent-Type: application/x-www-form-urlencoded\r\nReferer: http://localhost:8080/xxxxxxx.htm\r\nAccept-Language: es-ES,es;q=0.8,en-GB;q=0.5,en;q=0.3\r\nAccept-Encoding: gzip, deflate\r\nUser-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0; WebView/1.0)\r\nHost: localhost:8080\r\nContent-Length: 2537\r\nConnection: Keep-Alive\r\nCache-Control: no-cache\r\nCookie: port=8080\r\n\r\n"
The content-length is 2537, but there is no content. So, I don't know what's the problem. Maybe the webview sends two packet (http header and form content) and... I don't know.
I tried to read from socket again, when all the content is not ready, but VS throws: Error 0x80072746 The remote host closed the connection.
Thanks!
You are passing InputStreamOptions.Partial
to ReadAsync
. This implies that ReadAsync
may return with less than BUFFER_SIZE
even when there is more data in the wire.
Try using InputStreamOptions.None
instead. But this may not work in your case, because the connection will remain open and ReadAsync will block. You will need to parse the Content-Length
value from the headers, and read that amount of bytes after the \r\n\r\n
.
With the comment of Kiewic, the ugly script that works:
StringBuilder inputRequestBuilder = new StringBuilder();
List<byte> bytes = new List<byte>();
List<byte> last4bytes = new List<byte>();
string request = null;
using (var input = socket.InputStream.AsStreamForRead())
{
int b;
while (true)
{
try
{
b = input.ReadByte();
}
catch(Exception e) {
FileManager.WriteToDebug(e.ToString());
break;
}
bytes.Add((byte)b);
if (last4bytes.Count < 4)
{
last4bytes.Add((byte)b);
}
else
{
last4bytes.RemoveAt(0);
last4bytes.Add((byte)b);
if (last4bytes.ElementAt(0) == 13 && last4bytes.ElementAt(1) == 10
&& last4bytes.ElementAt(2) == 13 && last4bytes.ElementAt(3) == 10)
{
//after \r\n\r\n there is the content
byte[] byteArray = bytes.ToArray();
request = Encoding.UTF8.GetString(byteArray, 0, byteArray.Length);
inputRequestBuilder.Append(request);
string contentLength = getValueFromHeader("Content-Length", request);
if (!contentLength.Equals(""))
{
int length = Convert.ToInt32(contentLength);
if (length > 0)
{
byteArray = new byte[length];
input.Read(byteArray, 0, length);
var dataString = Encoding.UTF8.GetString(byteArray, 0, byteArray.Length);
inputRequestBuilder.Append(dataString);
}
}
break;
}
}
}
}
request = inputRequestBuilder.ToString();
User contributions licensed under CC BY-SA 3.0