I transfer a video stream from one c# app to another. When I set the frame rate high I don't get the right data after some time.
//Receiver
Socket s;
IPAddress ipAd = IPAddress.Parse("127.0.0.1");
var ip = IPAddress.Any;
myList = new TcpListener(ipAd, 8001);
myList.Start();
s = myList.AcceptSocket();
while (runThread)
{
int buffertype = -1; MemoryStream img = null; int size = 0; int
pos = 0;
try
{
// length of frame
byte[] lengthb = new byte[32];
int k = s.Receive(lengthb, SocketFlags.None);
size = BitConverter.ToInt32(lengthb, 0);
pos = 0;
byte[] lengthframe = new byte[size];
// chunking of data
int chunksize = 100;
while (pos < size - chunksize)
{
int rec = s.Receive(lengthframe, pos, chunksize, SocketFlags.None);
pos += rec;
}
s.Receive(lengthframe, pos, size - pos, SocketFlags.None);
img = new MemoryStream(lengthframe);
}
}
// Other app: Sender (all is send)
MemoryStream ms = new MemoryStream();
img.CopyTo(ms);
byte[] ba = ms.ToArray();
var buffer = BitConverter.GetBytes(ba.Length);
stm.Write(buffer, 0, buffer.Length);
stm.Write(ba, 0, ba.Length);
How can I be safe that all packages are received?
sender:
stm.Write(buffer, 0, buffer.Length);
receiver:
byte[] lengthb = new byte[32];
int k = s.Receive(lengthb, SocketFlags.None);
are you sure buffer.Length type is 32 bytes long (256 bits)? I suppose it's rather 4 or 8 bytes long. So you're potentially receiving 32 bytes buffer which includes your length field in the beggining and the rest is a part of your encoded video stream. Then you throw away that part. Doesn't sound good.
Related
In the below, I read the files from the Bluetooth device. Is there is any way to improve the code and speed?
using (FileStream fs = new FileStream(destination,
FileMode.OpenOrCreate,
FileAccess.ReadWrite))
{
byte[] firstByte = new byte[1] { (byte)readByte };
fs.Write(firstByte, 0, 1);
// Size is idenitifed. Read till that size.
for (int i = 1; i < fileSizeInBytes; i++)
{
readByte = 0;
byte[] fb = new byte[1];
if ((readByte = inStream.Read(fb, 0, 1)) > 0)
{
fs.Write(fb, 0, readByte);
}
}
}
Try using this - it creates a new byte array of a larger size and copies the elements from yours.
Array.Resize(ref readByte, 1024);
I am trying to encode a recorded audio using Nspeex and then transfer it over internet and decode on the other end. I am doing all this in Windows Phone 7/8. To encode and decode I am using following code. But while decoding I am not getting the result back correctly which I can play again. Can anyone provide me with encoding and decoding code which runs on WP7/8 recorded audio:
private static Microphone mic = Microphone.Default;
private static byte[] EncodeSpeech(byte[] buf, int len)
{
BandMode mode = GetBandMode(mic.SampleRate);
SpeexEncoder encoder = new SpeexEncoder(mode);
// set encoding quality to lowest (which will generate the smallest size in the fastest time)
encoder.Quality = 1;
int inDataSize = len / 2;
// convert to short array
short[] data = new short[inDataSize];
int sampleIndex = 0;
for (int index = 0; index < len; index += 2, sampleIndex++)
{
data[sampleIndex] = BitConverter.ToInt16(buf, index);
}
// note: the number of samples per frame must be a multiple of encoder.FrameSize
inDataSize = inDataSize - inDataSize % encoder.FrameSize;
var encodedData = new byte[len];
int encodedBytes = encoder.Encode(data, 0, inDataSize, encodedData, 0, len);
if (encodedBytes != 0)
{
// each chunk is laid out as follows:
// | 4-byte total chunk size | 4-byte encoded buffer size | <encoded-bytes> |
byte[] inDataSizeBuf = BitConverter.GetBytes(inDataSize);
byte[] sizeBuf = BitConverter.GetBytes(encodedBytes + inDataSizeBuf.Length);
byte[] returnBuf = new byte[encodedBytes + sizeBuf.Length + inDataSizeBuf.Length];
sizeBuf.CopyTo(returnBuf, 0);
inDataSizeBuf.CopyTo(returnBuf, sizeBuf.Length);
Array.Copy(encodedData, 0, returnBuf, sizeBuf.Length + inDataSizeBuf.Length, encodedBytes);
return returnBuf;
}
else
return buf;
}
private byte[] DecodeSpeech(byte[] buf)
{
BandMode mode = GetBandMode(mic.SampleRate);
SpeexDecoder decoder = new SpeexDecoder(mode);
byte[] inDataSizeBuf = new byte[4];
byte[] sizeBuf = new byte[4];
byte[] encodedBuf = new byte[buf.Length - 8];
Array.Copy(buf, 0, sizeBuf, 0, 4);
Array.Copy(buf, 4, inDataSizeBuf, 0, 4);
Array.Copy(buf, 8, encodedBuf, 0, buf.Length - 8);
int inDataSize = BitConverter.ToInt32(inDataSizeBuf, 0);
int size = BitConverter.ToInt32(sizeBuf, 0);
short[] decodedBuf = new short[inDataSize];
int decodedSize = decoder.Decode(encodedBuf, 0, encodedBuf.Length, decodedBuf, 0, false);
byte[] returnBuf = new byte[inDataSize * 2];
for (int index = 0; index < decodedBuf.Length; index++)
{
byte[] temp = BitConverter.GetBytes(decodedBuf[index]);
Array.Copy(temp, 0, returnBuf, index * 2, 2);
}
return returnBuf;
}
private static BandMode GetBandMode(int sampleRate)
{
if (sampleRate <= 8000)
return BandMode.Narrow;
if (sampleRate <= 16000)
return BandMode.Wide;
return BandMode.UltraWide;
}
I think your problem may be that you are newing up a new SpeexEncoder every time you want to encode audio. You should try making that a member for your class and re-use it.
I looked at the code for Nspeex I noticed that SpeexEncoder uses NbEncoder for the narrow band. In that class it looks like it keeps a history of some previous audio data in order perform the encoding. This should mean that the output for different instances of encoders would not go together.
private static Microphone mic = Microphone.Default;
private static SpeexEncoder encoder = CreateEncoder();
private static SpeexEncoder CreateEncoder()
{
BandMode mode = GetBandMode(mic.SampleRate);
SpeexEncoder encoder = new SpeexEncoder(mode);
// set encoding quality to lowest (which will generate the smallest size in the fastest time)
encoder.Quality = 1;
return encoder;
}
private static byte[] EncodeSpeech(byte[] buf, int len)
{
int inDataSize = len / 2;
...
I am transferring files using c#. I have used this code. The problem is small files like .txt files are transferred correctly but not big files like images, documents, pdf, ppt. Sometimes code works fine but most of the times it transfers less amount of data.
Server Code:
Socket clientSock = sock.Accept();
byte[] clientData = new byte[1024 * 50000];
int receivedBytesLen = clientSock.Receive(clientData);
int fileNameLen = BitConverter.ToInt32(clientData, 0);
string fileName = Encoding.ASCII.GetString(clientData, 4, fileNameLen);
BinaryWriter bWrite = new BinaryWriter(File.Open(receivedPath + "/" + fileName, FileMode.Append));
bWrite.Write(clientData, 4 + fileNameLen, receivedBytesLen - 4 - fileNameLen);
bWrite.Close();
clientSock.Close();
Client Code:
byte[] fileNameByte = Encoding.ASCII.GetBytes(fileName);
byte[] fileData = File.ReadAllBytes(filePath + fileName);
byte[] clientData = new byte[4 + fileNameByte.Length + fileData.Length];
byte[] fileNameLen = BitConverter.GetBytes(fileNameByte.Length);
fileNameLen.CopyTo(clientData, 0);
fileNameByte.CopyTo(clientData, 4);
fileData.CopyTo(clientData, 4 + fileNameByte.Length);
clientSock.Connect(ipEnd);
clientSock.Send(clientData);
clientSock.Close();
Complete code is given in the above link. I have also seen this post but this is not helpful.
Sometimes code works fine but most of the times it transfers less amount of data.
That's the nature of Socket.Receive(), it doesn't always return all data that gets sent to it.
You'll have to do a Receive(clientData, 4, 0) first to receive the bytes that indicate the size , then call Receive(clientData) in a loop until you've received size bytes. But beware that the Receive(buffer[], length, offset) overload just as easily as any other overload can return less than the expected amount of bytes. So you'll also have to call that in a loop:
Something like this:
// First receive the size
int sizeSize = 4; // Size of Int32 in bytes
int sizeOffset = 0;
var sizeBytes = new byte[sizeSize];
while (sizeOffset < sizeSize)
{
sizeOffset += clientSocket.Receive(sizeBytes, sizeSize - sizeOffset, sizeOffset);
}
var size = BitConverter.ToInt32(sizeBytes, 0);
// Then receive the data
byte[] fileData = new byte[size];
byte[] clientData = new byte[8192];
int totalBytes = 0;
while (totalBytes < size)
{
// This may return anything between 0 and 8192, even if not all sent data has been received yet. It may be in a buffer somewhere, waiting to be picked up. Check for 0, since that's when the client disconnects.
int bytesReceived = clientSocket.Receive(clientData);
// You now have received a chunk of data of bytesReceived length. Append it into the fileData array.
Buffer.BlockCopy(clientData, 0, fileData, totalBytes, bytesReceived);
totalBytes += bytesReceived;
}
As CodeCaster's answered that Socket.Receive(), it doesn't always return all data that gets sent to it. This is 100% correct and tested but the next step of sending the file size is not working, I found an easy and correct solution.
Socket.Receive() method takes the byte array in which received data will be copied and returns the number of bytes received. So we can easily loop it till bytes received are 0.
byte[] tempData = new byte[1024 * 5000];
BinaryWriter bWrite = null;
int bytes_received;
int fileNamelength = 0;
bool isFirstPacket = true;
do
{
bytes_received = clientSock.Receive(tempData);
if(isFirstPacket)
{
isFirstPacket = false;
int fileNameLen = BitConverter.ToInt32(tempData, 0);
string fileName = Encoding.ASCII.GetString(clientData, 4, fileNameLen);
bWrite = new BinaryWriter(File.Open(receivedPath + fileName, FileMode.Append))
bWrite.Write(tempData, 4 + fileNameLength, bytes_received - 4 - fileNamelength);
}
else
bWrite.Write(tempData, 0, bytes_received);
}
while (bytes_received != 0);
I made a client & server that establishes a TCP connection through sockets, I'm trying to send binary data over the socket but I could only send txt or pdf files, I had no luck with exe files, I use fread and fseek to read the file and split it into a buffer. When I read the whole exe file it gets sent successfully but when I split it, it gets sent corrupted!
I read some books about sockets but I still don't know much and I have some questions.
is it okay to send the whole file in one send()?? or I should continue with sending it in small chunks?
Also, why exe files get corrupted when I send them in chunks?
Thank you!
Client Code (in c):
int bufSize = 10000;
int sentBytes = 0;
FILE * pFile;
long remainingBytes;
char * buffer;
size_t result;
pFile = fopen ( "D:\\file.exe" , "rb" );
fseek (pFile , 0 , SEEK_END);
remainingBytes = ftell (pFile);
rewind (pFile);
int bufferSize = remainingBytes > bufSize ? bufSize : remainingBytes;
buffer = (char*) malloc (sizeof(char)*bufferSize);
send(Socket, (char*)&remainingBytes, 4, 0);
while(remainingBytes > 0)
{
fseek (pFile , sentBytes , SEEK_SET);
result = fread(buffer,1,bufferSize,pFile);
if(bufferSize < remainingBytes)
{
send(Socket, buffer, bufferSize, 0);
}
else
{
send(Socket, buffer, remainingBytes, 0);
bufferSize = remainingBytes;
}
remainingBytes -= bufferSize;
sentBytes += bufferSize;
}
Server code (in c#)
try
{
int bufferSize = 200;
int len = 0;
int receivedBytes = 0;
int remainingBytes = len;
byte[] length = new byte[4];
//byte[] imgBuf = new byte[bufferSize];
int current = 0;
List<byte[]> coming = new List<byte[]>();
sockets[number].Receive(length,4,0);
len = BitConverter.ToInt32(length, 0);
remainingBytes = len;
bufferSize = len < bufferSize ? len : bufferSize;
while(receivedBytes < len)
{
if (remainingBytes > bufferSize)
{
coming.Add(new byte[bufferSize]);
//imgBuf = new byte[bufferSize];
sockets[number].Receive(coming[current], bufferSize, 0);
}
else
{
coming.Add(new byte[remainingBytes]);
//imgBuf = new byte[remainingBytes];
sockets[number].Receive(coming[current], remainingBytes, 0);
bufferSize = remainingBytes;
}
remainingBytes -= bufferSize;
receivedBytes += bufferSize;
current++;
//Array.Clear(imgBuf, 0, imgBuf.Length);
}
using (var stream = new FileStream(#"C:\receivedFile.exe",FileMode.Create))
{
using (var binaryWriter = new BinaryWriter(stream))
{
foreach (byte[] buffer in coming)
{
binaryWriter.Write(buffer);
}
}
}
}
catch (Exception ex)
{ this.setText(ex.Message, textBox2); }
Edit: Thanks for the help, I got it working :)
try
{
int bufferSize = 1024 * 100;
int len = 0;
int receivedBytes = 0;
int remainingBytes = len;
int reached = 0;
byte[] length = new byte[4];
byte[] imgBuf = new byte[bufferSize];
int current = 0;
sockets[number].Receive(length,4,0);
len = BitConverter.ToInt32(length, 0);
remainingBytes = len;
bufferSize = len < bufferSize ? len : bufferSize;
imgBuf = new byte[len];
while (reached < len)
{
reached += sockets[number].Receive(imgBuf, receivedBytes, remainingBytes, 0);
remainingBytes = len - reached;
receivedBytes = reached;
current++;
//Array.Clear(imgBuf, 0, imgBuf.Length);
}
using (var stream = new FileStream(#"C:\putty.exe",FileMode.Create))
{
using (var binaryWriter = new BinaryWriter(stream))
{
binaryWriter.Write(imgBuf);
}
}
Array.Clear(imgBuf, 0, imgBuf.Length);
}
catch (Exception ex)
{ this.setText(ex.Message, textBox2); }
You don't check how many bytes you actually received in sockets[number].Receive(coming[current], bufferSize, 0); . It doesn't have to be equal to the buffer size you have declared.
Additionaly, as said in comments, keeping whole file in memory is not a good idea.
In addition to checking the number of bytes received, you need to check the number of bytes sent by each send call -- if your TCP transmit window fills up, a send call might send less data than you requested, in which case the you'll need to resend the unsent data.
In general, you ALWAYS need to check the return value of your system calls to check for the all the various odd corner cases that can occur. Read the man pages for send(2) and recv(2) for a full list of everything that can happen.
With windows Azure Storage Client Library, CloudBlob.OpenRead() method reads only 4 mb of data. How can I read full stream using OpenRead method.
CloudBlob blob = container.GetBlobReference(filename);
Stream stream = blob.OpenRead();
I must use OpenRead method. Can't use DownloadToFile or DownloadToStream.
EDIT :
The consumer code which is outside my scope calls
stream.CopyTo(readIntoStream);
CopyTo is an extension method.
public static int CopyTo(this Stream source, Stream destination)
{
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead;
int bytesCopied = 0;
do
{
bytesRead = source.Read(buffer, 0, BUFFER_SIZE);
if (bytesRead > 0)
destination.Write(buffer, 0, bytesRead);
bytesCopied += bytesRead;
}
while (bytesRead > 0);
return bytesCopied;
}
EDIT 2 :
I have observed that when file is uploaded using blob.UploadText() method, it works fine but when blob is uploaded using OpenWrite method as done in following code sample, the OpenRead Method reads only 4194304 bytes (4 mb).
using(var input = File.OpenRead(#"C:\testFile.txt")) //5000000 bytes
using (var output = blob.OpenWrite())
{
input.CopyTo(output);
}
EDIT 3 :
Complete code that produces the issue at my end.
static void Main(string[] args)
{
var blobContainer = GetContainer("tier1");
blobContainer.CreateIfNotExist();
var containerPermissions = new BlobContainerPermissions();
containerPermissions.PublicAccess = BlobContainerPublicAccessType.Blob;
blobContainer.SetPermissions(containerPermissions);
var blob = blobContainer.GetBlobReference("testfileWithOpenWrite1.txt");
using (var input = File.OpenRead(#"C:\testFile.txt")) //5000000 bytes
using (var output = blob.OpenWrite(new BlobRequestOptions()))
input.CopyTo(output);
Console.WriteLine("uploaded");
int bytesDownloaded = 0;
byte[] buffer = new byte[65536];
using (BlobStream bs = blob.OpenRead())
{
int chunkLength;
do
{
chunkLength = bs.Read(buffer, 0, buffer.Length);
bytesDownloaded += chunkLength;
} while (chunkLength > 0);
}
Console.WriteLine(bytesDownloaded);
}
public static int CopyTo(this Stream source, Stream destination)
{
int BUFFER_SIZE = 65536;
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead;
int bytesCopied = 0;
do
{
bytesRead = source.Read(buffer, 0, BUFFER_SIZE);
if (bytesRead > 0)
destination.Write(buffer, 0, bytesRead);
bytesCopied += bytesRead;
}
while (bytesRead > 0);
return bytesCopied;
}
EDIT 4 - Conclusion:
This was probably a bug in Microsoft.WindowsAzure.StorageClient.dll (assembly version 6.0.6002.17043) that comes with SDK v1.2. It works with latest Microsoft.WindowsAzure.StorageClient.dll (assembly version 6.0.6002.18312 - SDK v1.4).
Thanks smarx :)
I can't reproduce what you're seeing. Things seem to work as expected:
static void Main(string[] args)
{
// I also tried a real cloud storage account. Same result.
var container = CloudStorageAccount.DevelopmentStorageAccount.CreateCloudBlobClient().GetContainerReference("testcontainer");
container.CreateIfNotExist();
var blob = container.GetBlobReference("testblob.txt");
blob.UploadText(new String('x', 5000000));
var source = blob.OpenRead();
int BUFFER_SIZE = 4000000;
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead;
int bytesCopied = 0;
do
{
bytesRead = source.Read(buffer, 0, BUFFER_SIZE);
bytesCopied += bytesRead;
} while (bytesRead > 0);
Console.WriteLine(bytesCopied); // prints 5000000
}
EDIT:
I've also (in response to the edited question) now tried uploading the blob using OpenWrite, and the result is the same. (I get the full blob back.) I used this code in place of blob.UploadText(...):
using (var input = File.OpenRead(#"testblob.txt")) //5000000 bytes
using (var output = blob.OpenWrite())
{
input.CopyTo(output);
}
The final WriteLine still prints 5000000.
EDIT 2:
This is getting a bit tiresome. Changing the BUFFER_SIZE to 65536 didn't change anything. The results still seem correct to me. Here's my full application for comparison:
static void Main(string[] args)
{
// I also tried a real cloud storage account. Same result.
var container = CloudStorageAccount.DevelopmentStorageAccount.CreateCloudBlobClient().GetContainerReference("testcontainer");
container.CreateIfNotExist();
var blob = container.GetBlobReference("testblob.txt");
using (var input = File.OpenRead(#"testblob.txt")) //5000000 bytes
using (var output = blob.OpenWrite())
{
input.CopyTo(output);
}
var source = blob.OpenRead();
int BUFFER_SIZE = 65536;
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead;
int bytesCopied = 0;
do
{
bytesRead = source.Read(buffer, 0, BUFFER_SIZE);
bytesCopied += bytesRead;
} while (bytesRead > 0);
Console.WriteLine(bytesCopied); // prints 5000000
}