Protocol buffer net with windows phone 7 - c#

I'm trying to download a response from a server wich is in Protocol Buffer format from a Windows Phone 7 application.
I'm trying to do this with a WebClient, my problem is the following.
The WebClient has only two method for downloading
DownloadStringAsync(new Uri(url));
and
OpenReadAsync(new Uri(url));
but this two method are not good to retrieve the response because, the response size should have 16 hexadecimal caracteres ( 080118CBDDF0E104 ), but the size of the string and the stream get by the two methods are only 8.
So I'm searching a way to resolve my problem.
I found one for C#
public static T DownloadProto<T>(this WebClient client, string address)
{
byte[] data = client.DownloadData(address);
using (var ms = new MemoryStream(data))
{
return Serializer.Deserialize<T>(ms);
}
}
on
http://code.google.com/p/protobuf-net/source/browse/trunk/BasicHttp/HttpClient/ProtoWebClient.cs?spec=svn340&r=340
But this method was deleted or not yet implemented on the Windows Phone 7 development kit.

How are you reading from the stream?
If you are reading it as a string then its perhaps reading two bytes per character - instead use
var buf = new byte[16];
var actual = stream.Read(buf, 0, buf.Length);

Related

Not compelete result from Azure speech to text API

I have a small wav sound file in which I want to get the text of it, so I used Azure speech to text API to test it.
first thing I convert the audio file as they recommended in their documentation to PCM - Mono -16K sample rate.
and I use this code in c# in the documentation example here to upload the file and get the result.
HttpWebRequest request = null;
request = (HttpWebRequest)HttpWebRequest.Create("https://speech.platform.bing.com/speech/recognition/interactive/cognitiveservices/v1?language=en-US&format=detailed");
request.SendChunked = true;
request.Accept = #"application/json;text/xml";
request.Method = "POST";
request.ProtocolVersion = HttpVersion.Version11;
request.ContentType = #"audio/wav; codec=audio/pcm; samplerate=16000";
request.Headers["Ocp-Apim-Subscription-Key"] = "my key";
// Send an audio file by 1024 byte chunks
using (FileStream fs = new FileStream("D:/b.wav", FileMode.Open, FileAccess.Read))
{
/*
* Open a request stream and write 1024 byte chunks in the stream one at a time.
*/
byte[] buffer = null;
int bytesRead = 0;
using (Stream requestStream = request.GetRequestStream())
{
/*
* Read 1024 raw bytes from the input audio file.
*/
buffer = new Byte[checked((uint)Math.Min(1024, (int)fs.Length))];
while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) != 0)
{
requestStream.Write(buffer, 0, bytesRead);
}
// Flush
requestStream.Flush();
}
}
string responseString;
Console.WriteLine("Response:");
using (WebResponse response = request.GetResponse())
{
Console.WriteLine(((HttpWebResponse)response).StatusCode);
using (StreamReader sr = new StreamReader(response.GetResponseStream()))
{
responseString = sr.ReadToEnd();
}
Console.WriteLine(responseString);
Console.ReadLine();
}
also i tried using cUrl tool and also write it in java as i was thought that maybe it's problem with the programming language I use that i not upload the file correctly.
this the link of the sound file i want to convert it to text here.
so Now i need to help to figure it out if the problem comes from the format of the sound file? or from maybe code that i not upload it correctly? or it's from the API I mean to be not accurate enough?
i tried IBM speech to text and it got all the text with no problem.
iam using now the free trial of Azure speech to text API and I want to figure where the problem comes if anyone has experience with this to see if I will work with this API or not.
Update
I want to clear that iam not got any error i just got incomplete result to my sound file I upload, for example the sound file i upload he said at the end of the sound "What is up with that", the result i got from Azure is just the first sentence only which is "I say that like it's a bad thing.", also I upload another sound file which contains the "What is up with that" only check it here,and it just gives me an empty result like this.
{"RecognitionStatus":"NoMatch","Offset":17300000,"Duration":0}
so all that i want to know if this normal from the Speech to text API Azure or the problem with my code or from the sound file? this what i want to get an answer with it.
when i test another API on those files it worked like IBM for example.
Thanks in advance.

C# TCP data transfer with BinarySerializer

I am attempting to connect my laptop with my standalone pc using C# TCPClient class.
Laptop is running a simple console application and plays the role of the server.
PC is a Unity aplication (2018.1.6f1 with .Net4.x Mono)
The code for sending is
public void SendData() {
Debug.Log("Sending data");
NetworkStream ns = client.GetStream();
BinaryFormatter bf = new BinaryFormatter();
TCPData data = new TCPData(true);
using (MemoryStream ms = new MemoryStream()) {
bf.Serialize(ms, data);
byte[] bytes = ms.ToArray();
ns.Write(bytes, 0, bytes.Length);
}
}
The same code is used in the Laptop's project, except Debug.Log() is replaced by Console.WriteLine()
For data reception I use
public TCPData ReceiveData() {
Debug.Log("Waiting for Data");
using (MemoryStream ms = new MemoryStream()) {
byte[] buffer = new byte[2048];
int i = stream.Read(buffer, 0, buffer.Length);
stream.Flush();
ms.Write(buffer, 0, buffer.Length);
ms.Seek(0, SeekOrigin.Begin);
BinaryFormatter bf = new BinaryFormatter();
bf.Binder = new CustomBinder();
TCPData receivedData = (TCPData)bf.Deserialize(ms);
Debug.Log("Got the data");
foreach (string s in receivedData.stuff) {
Debug.Log(s);
}
return receivedData;
}
}
Again the same on both sides,
The data I am trying to transfer looks like this
[Serializable, StructLayout(LayoutKind.Sequential)]
public struct TCPData {
public TCPData(bool predefined) {
stuff = new string[2] { "Hello", "World" };
ints = new List<int>() {
0,1,2,3,4,5,6,7,8,9
};
}
public string[] stuff;
public List<int> ints;
}
The custom binder is from here
without it I get an assembly error
with it I get Binary stream '0' does not contain a valid BinaryHeader. Possible causes are invalid stream or object version change between serialization and deserialization.
Now the problem:
Sending this from PC to Laptop - 100% success rate
Sending this from Laptop to PC - 20% success rate (80% is the Exception above)
How is it even possible that it "sometimes" works ?
Shouldn't it be 100% or 0% ?
How do I get it to work ?
Thanks
E: Ok thanks to all the suggestions I managed to increase the chances of success, but it still occasionally fails.
I send a data size "packet" which is 80% of the time received correctly, but in some cases the number I get from the byte[] is 3096224743817216 (insanely big) compared to the sent ~500.
I am using Int64 data type.
E2: In E1 I was sending the data length packet separately, now I have them merged, which does interpret the length properly, but now I am unable to deserialize the data... every time I get The input stream is not a valid binary format. The starting contents (in bytes) are: 00-00-00-00-00-00-04-07-54-43-50-44-61-74-61-02-00 ...
I read the first 8 bytes from the stream and the remaining 'x' are the data, deserializing it on server works, deserializing the same data throws.
E3: Fixed it by rewriting the stream handling code, I made a mistake somewhere in there ;)
NetworkStream.Read() doesn't block until it reads the requested number of bytes:
"This method reads data into the buffer parameter and returns the number of bytes successfully read. If no data is available for reading, the Read method returns 0. The Read operation reads as much data as is available, up to the number of bytes specified by the size parameter. If the remote host shuts down the connection, and all available data has been received, the Read method completes immediately and return zero bytes."
You must
1) Know how many bytes you are expecting
and
2) Loop on Read() until you have received the expected bytes.
If you use a higher-level protocol like HTTP or Web Sockets they will handle this "message framing" for you. If you code on TCP/IP directly, then that's your responsibility.

HttpWebRequest error read more than 65536 bytes on WP8.1

Code below read bytes from MJPEG video stream.
It works perfectly on Windows 8.1 Store application, but the same code fail on Windows phone 8.1 application.
After reading 65536 bytes method "Read" not read more bytes from stream.
The same problem in On WP8.1 ONLY: cannot read more than 65536 bytes off an HTTP Stream
Someone tells about property DefaultMaximumErrorResponseLength but this property is only in WPF (not in windows store .net)
WebClient class on WP8.1 has the same problem.
(in On WP8.1 ONLY: cannot read more than 65536 bytes off an HTTP Stream says that WebClient don't have this problem, but it don't true)
Sample code:
var request = (HttpWebRequest)WebRequest.CreateHttp("http://webcam.st-malo.com/axis-cgi/mjpg/video.cgi?resolution=352x288");
request.AllowReadStreamBuffering = false;
request.BeginGetResponse(OnGetResponse, request);
private void OnGetResponse(IAsyncResult asyncResult)
{
HttpWebRequest req = (HttpWebRequest)asyncResult.AsyncState;
HttpWebResponse resp = (HttpWebResponse)req.EndGetResponse(asyncResult);
Stream s = resp.GetResponseStream();
byte[] buff = new byte[ChunkSize];
int readed;
do
{
readed = s.Read(buff, 0, ChunkSize);
}
while (readed > 0);
}

.NET HTTPReguest GetResponse() get first N bytes

I'm trying to create a website crawler. it's going to retrieve some data from many websites.
some times if I load just 1000 first bytes of a webpage, I can see what I am looking for.
here is my code:
request = (HttpWebRequest)WebRequest.Create("http://example.com");
var response = (HttpWebResponse)request.GetResponse();
string responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
when I call request.GetResponse(), it will load whole the page (for example 4000 bytes) but the data that I'm looking for is in the first 1000 bytes. and when I call ReadToEnd(), it will read all the received data from RAM. but whole the data sent to my computer from the website! I don't want to receive all bytes, I need only N bytes of the first.
If I can do it so I save many many internet traffic.
can you help me? how can I do that?
Use StreamReader.Read, eg.
StreamReader sr = new StreamReader(response.GetResponseStream());
char[] c = new char[1000]; // 1000 bytes
sr.Read(c, 0, c.Length);
string responseString = new string(c);

PHP => Inflate GZipped string coming from C# SharpZipLib?

i have a C# application where i am using SharpZipLib to deflate a very long string and then send the data over to a PHP Service in a Base64 string of the deflated byte[].
For some reason, when trying to Inflate it on the PHP side, it is returning an error: 'gzinflate: data error'.
How to inflate a gzipped string in PHP?
Here is the C# code:
byte[] sIn = System.Text.UTF8Encoding.UTF8.GetBytes(data);
MemoryStream rawDataStream = new MemoryStream();
GZipOutputStream gzipOut = new GZipOutputStream(rawDataStream);
gzipOut.IsStreamOwner = false;
gzipOut.Write(sIn, 0, sIn.Length);
gzipOut.Close();
byte[] compressed = rawDataStream.ToArray();
// data sent to the php service
string b64 = Convert.ToBase64String(compressed);
PHP code:
$inflated = base64_decode($_POST['data']);
// crash here
$inflated = gzinflate($inflated);
Thanks in advance!
Can't really say why it fails for you with GZipOutStream though I'm guessing it is doing something else then just a pure deflate-compression. I changed your code to use DeflateStream from System.IO.Compression instead and then it worked like a charm.
byte[] sIn = UTF8Encoding.UTF8.GetBytes("testing some shit");
MemoryStream rawDataStream = new MemoryStream();
DeflateStream gzipOut = new DeflateStream(rawDataStream, CompressionMode.Compress);
gzipOut.Write(sIn, 0, sIn.Length);
gzipOut.Close();
byte[] compressed = rawDataStream.ToArray();
// data sent to the php service
string b64 = Convert.ToBase64String(compressed);
Edit
Since the question was about using compression for a Windows Phone project I tried using the DeflateStream from SharpCompress as well and it works just fine, you just have to change which namespace you are using, the classes are the same.

Categories