my program right now is sending a screen shot from one computer to the other but the result on the receiving side the img looks like:
Bitmap bmpScreenShot = new Bitmap(screenWidth, screenHeight);
Graphics gfx = Graphics.FromImage((Image)bmpScreenShot);
gfx.CopyFromScreen(0, 0, 0, 0, new Size(screenWidth, screenHeight));
bmpScreenShot.Save("pic.jpg", ImageFormat.Jpeg);
MemoryStream ms = new MemoryStream();
bmpScreenShot.Save(ms, ImageFormat.Jpeg);
bmpbyte = ms.ToArray();
bmpScreenShot.Dispose();
ms.Close();
///////////////////////////
Send_Text("" + screenHeight);
textBox3.Text += ("\r\nSending Hight=" + screenHeight);
Send_Text("" + screenWidth);
textBox3.Text += ("\r\nSending Width=" + screenWidth);
System.Threading.Thread.Sleep(200);
Send_Text("" + bmpbyte.Length);
textBox3.Text += ("\r\nSending size of:" + bmpbyte.Length);
textBox3.Text += "\r\nTransmiting the Screenshot";
stm.Write(bmpbyte, 0, bmpbyte.Length);
textBox3.Text += "\r\nSent IMG :)";
the code on top is the client side of it
im sending the size of the pic (hight and width and array length) and it transfers properly
but the server as i said has trobles getting the full pic
textBox2.Text += "\r\n Getting h";
byte[] buffer = new byte[320];
s.Receive(buffer);
string str = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
Array.Clear(buffer, 0, buffer.Length);
int h = int.Parse(str);
textBox2.Text += "="+h+"\r\n Getting w";
s.Receive(buffer);
str = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
Array.Clear(buffer, 0, buffer.Length);
int w = int.Parse(str);
textBox2.Text += "="+w+"\r\n Getting p";
s.Receive(buffer);
str = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
Array.Clear(buffer, 0, buffer.Length);
int p = int.Parse(str);
textBox2.Text += "=" + p;
byte[] asd = new byte[p];
Bitmap cc = new Bitmap(h, w);
s.Receive(asd);
MemoryStream ms = new MemoryStream(asd);
Image bmp = Image.FromStream(ms);
bmp.Save("End.jpg", ImageFormat.Jpeg);
pictureBox1.Image = bmp;
plz note that alll of the undefined things are defind some where in the code
and the text box lines are just for the user interface
one more thing im using the localhost \local network and it all tcp
You're not telling us how you send the information (over network? serial? TCP?), but from your code I can see one thing:
You do receive the actual number of bytes to wait for, but you're not waiting for the actual number of bytes.
byte[] asd = new byte[p];
s.Receive(asd);
This does create a byte array large enough to keep all the bytes, but does s.Receive(asd) really receive all the bytes?
After you edited your question, let me clarify one thing: TCP communication can be fragmented. Just because you send 4000 bytes in one go does not guarantee the receiver to receive 4000 bytes in one go. He probably won't. That's why the Receive method returns the actual number of bytes received.
So what your receiver needs to do is this (pseudo code):
int totalBytesRead = 0;
do
{
int bytesRead = s.Receive(buffer);
totalBytesRead += bytesRead;
if (bytesRead == 0)
{
// Stream was closed - no more bytes
break;
}
else
{
// Write bytesRead bytes from buffer to memory stream
}
}
while (totalBytesRead < expectedNumberOfBytes);
if (totalBytesRead < expectedNumberOfBytes)
throw new Exception("Premature end of transmission");
Actually, thinking things through again and looking at your code I noticed that you're actually sending JPEG bytes to the receiver. It's highly improbable that an uninitialized buffer on the receiver's side should be valid JPEG.
So while all the above is still true, I now doubt that the receiver is actually the one doing things wrong. It seems now that saving the bytes to the memory stream doesn't work properly.
I see from your code you're saving the image both to a file and to a memory stream. Does the file contain a valid picture? If not you need to look for the cause of the screenshot not being created properly. If the picture is valid, you could try two other things:
Read the JPEG bytes from the file instead of creating a memory stream
Don't dispose of the memory stream before sending the bytes to the client, but after that
There are questions on SO that indicate that timing seems to be an issue when saving images to a memory stream and getting the bytes from the stream. Sometimes it won't work.
Related
I am new in the serial port. Currently, my project is to extract data from the machine. I'm getting data via an event onDataReceive and the machine is sending bytes.
My problem is that the first wave of bytes seemed to be converted correctly to string but in the second batch of bytes, I got garbage data.
Screen Shot of the output(this is the output given by the multi-currency reader machine:
The garbage data is I think the Serial Nos.
Here is my code in onDataReceive method:
private void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
while (serialPort.BytesToRead > 0)
{
// Initialize a buffer to hold the received data
byte[] buffer = new byte[serialPort.ReadBufferSize];
//// There is no accurate method for checking how many bytes are read
//// unless you check the return from the Read method
int bytesRead = serialPort.Read(buffer, 0, buffer.Length);
String asd = System.Text.ASCIIEncoding.ASCII.GetString(buffer, 0, bytesRead);
//// For the example assume the data we are received is ASCII data.
tString += Encoding.ASCII.GetString(buffer, 0, bytesRead);
temp += System.Text.Encoding.Unicode.GetString(buffer, 0, bytesRead);
temp2 += System.Text.Encoding.UTF32.GetString(buffer, 0, bytesRead);
System.IO.File.WriteAllText(#"C:\OutputTextFiles\WriteLines.txt", tString);
System.IO.File.WriteAllText(#"C:\OutputTextFiles\WriteLines2.txt", temp);
System.IO.File.WriteAllText(#"C:\OutputTextFiles\WriteLines3.txt", temp2);
}
}
I'm trying to put the output with a txt file.
I hope someone could help me in my problem. Any tips and suggestions in data handling especially bytes?
Without knowing the size of serialPort.ReadBufferSize I can only suspect that your buffer is breaking the encoding bytes of your string. A character can be made of one or more bytes.
The trick is to read all of the bytes before decoding the string.
Try this example program:
var encoding = System.Text.Encoding.Unicode;
var message = "I am new in serial port. Currently my project is to extract data from machine.";
using (var ms = new MemoryStream(encoding.GetBytes(message)))
{
var bytes = new List<byte>();
var buffer = new byte[23];
var bytesRead = ms.Read(buffer, 0, buffer.Length);
while (bytesRead > 0)
{
Console.WriteLine(encoding.GetString(buffer, 0, bytesRead));
bytes.AddRange(buffer.Take(bytesRead));
bytesRead = ms.Read(buffer, 0, buffer.Length);
}
Console.WriteLine(encoding.GetString(bytes.ToArray(), 0, bytes.Count));
}
It will output the following:
I am new in�
猀攀爀椀愀氀 瀀漀爀琀�
. Currently�
洀礀 瀀爀漀樀攀挀琀 �
is to extra�
琀 搀愀琀愀 昀爀漀洀�
machine.
I am new in serial port. Currently my project is to extract data from machine.
The final line is correct because it uses all of the bytes to decode. The previous lines have errors because I've used a buffer size of 23 which breaks the string encoding.
im trying to send an image through tcp, It works about 50% of the time, the other 50% is just giving me a black image and if i send 2 in the space of like 3 seconds it crashes. does anyone know why? and how i can fix this
Client:
while ((i = stream.Read(datalength, 0, 4)) != 0)
{
byte[] data = new byte[BitConverter.ToInt32(datalength, 0)];
stream.Read(data, 0, data.Length);
this.Invoke((MethodInvoker)delegate
{
try
{
Image Screenshot = byteArrayToImage(data);
pictureBox1.Image = Screenshot;
}
catch { }
});
}
This is the function which converts the byte array to image
public Image byteArrayToImage(byte[] byteArrayIn)
{
MemoryStream ms = new MemoryStream(byteArrayIn);
Image returnImage = Image.FromStream(ms);
return returnImage;
}
Server:
Bitmap printscreen = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
Graphics graphics = Graphics.FromImage(printscreen as Image);
graphics.CopyFromScreen(0, 0, 0, 0, printscreen.Size);
byte[] data = imageToByteArray(Image);
stream = client.GetStream();
int length = data.Length;
byte[] datalength = new byte[4];
datalength = BitConverter.GetBytes(length);
stream.Write(datalength, 0, 4);
stream.Write(data, 0, data.Length);
This is the function that converts the image to byte array
public byte[] imageToByteArray(System.Drawing.Image imageIn)
{
MemoryStream ms = new MemoryStream();
imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
return ms.ToArray();
}
You have to make sure that you read the entire "packet". It is not certain that you receive everything just because you request it. The Read() method will return how many bytes have been read, store that and loop until you've received the right amount of bytes.
Replace your current Read() with this:
int bytesReceived = 0;
while(bytesReceived < data.Length)
{
bytesReceived += stream.Read(data, bytesReceived, data.Length - bytesReceived);
}
This will read until your whole image has been received.
EDIT: Fixed a problem in code, thanks to Ivan's answer.
You're reading 1000 bytes when you should be reading four. You're reading and throwing away a large part of the image following the length word.
You're also apparently ignoring the result of read(), and assuming that it fills the buffer.
I am developing a WCF service that downloads a pdf file from a internet portal converts it into byte array and sends it to the client. On client side i am converting this byte array to pdf by using WriteAllBytes method. But while opening the pdf document it displays "There is error while opening the documnet. The file might be damaged or corrupted"
WCF Code
//
FileInformation fileInfo = File.OpenBinaryDirect(clientContext, fileRef.ToString());
byte[] Bytes = new byte[Convert.ToInt32(fileSize)];
fileInfo.Stream.Read(Bytes, 0, Bytes.Length);
return Bytes;
Client code
byte[] recievedBytes = <call to wcf method returing byte array>;
File.WriteAllBytes(path, recievedBytes);
I strongly suspect this is the problem:
byte[] Bytes = new byte[Convert.ToInt32(fileSize)];
fileInfo.Stream.Read(Bytes, 0, Bytes.Length);
You're assuming a single call to Read will read everything. Instead, you should loop round until you have read everything. For example:
byte[] bytes = new byte[(int) fileSize];
int index = 0;
while (index < bytes.Length)
{
int bytesRead = fileInfo.Stream.Read(bytes, index, bytes.Length - index);
if (bytesRead == 0)
{
throw new IOException("Unable to read whole file");
}
index += bytesRead;
}
Alternatively:
MemoryStream output = new MemoryStream((int) fileSize];
fileInfo.Stream.CopyTo(output);
return output.ToArray();
I'm trying to read a local file and upload it on ftp server. when i read a image file, everything is ok, but when i read a doc or docx file, FileStream returns length = 0. Here is my code:
i checked with some other files, it appears that it only works fine with images and it returns 0 for any other file
if (!ftpClient.FileExists(fileName))
{
try
{
ftpClient.ValidateCertificate += (control, e) => { e.Accept = true; };
const int BUFFER_SIZE = 64 * 1024; // 64KB buffer
byte[] buffer = new byte[BUFFER_SIZE];
using (Stream readStream = new FileStream(tempFilePath, FileMode.Open, FileAccess.Read))
using (Stream writeStream = ftpClient.OpenWrite(fileName))
{
while (readStream.Position < readStream.Length)
{
buffer.Initialize();
int bytesRead = readStream.Read(buffer, 0, BUFFER_SIZE);
writeStream.Write(buffer, 0, bytesRead);
}
readStream.Flush();
readStream.Close();
writeStream.Flush();
writeStream.Close();
DeleteTempFile(tempFilePath);
return true;
}
}
catch (Exception ex)
{
return false;
}
}
I couldn't find whats wrong with it. could you please help me?
While this doesn't answer your specific question, you don't actually need to know the length of your stream. Just keep reading until you hit a zero length read. A zero byte read is guaranteed to indicate the the end of any stream.
Return Value
Type: System.Int32
The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero (0) if the end of the stream has been reached.
while (true)
{
int bytesRead = readStream.Read(buffer, 0, BUFFER_SIZE);
if(bytesRead==0)
{
break;
}
writeStream.Write(buffer, 0, bytesRead);
}
alternatively:
readStream.CopyTo(writeStream);
is probably the most concise method of stating your goal...
it was just a silly mistake, i have two fileupload and i've saved the other fileupload, so it creates a zero length file. as it appears the code works fine.
thanks everyone.
I wanted to create a project for streaming multiple images through net. I just wanted to start with small, functional code but already encountered a funky problem for me. Image is received, but it contains graphical bugs like its only a part of it.
Sadly cant show images cause of low rputation, here is link.
http://img543.imageshack.us/img543/1508/buggedy.jpg
Of course, million dollars for answer. ^^
TcpListener listener;
TcpClient client;
TcpClient datatoclient;
NetworkStream stream;
Host part:
listener = new TcpListener(5000);
listener.Start();
datatoclient = listener.AcceptTcpClient();
NetworkStream nowystream = datatoclient.GetStream();
MemoryStream ms = new MemoryStream();
byte[] image = File.ReadAllBytes("default.jpg");
switch (trackBar1.Value)
{
case 0:
image = File.ReadAllBytes("mirrion.jpg");
break;
case 1:
image = File.ReadAllBytes("tenis.jpg");
break;
case 2:
image = File.ReadAllBytes("marisasold.jpg");
break;
}
// get the image size in bytes
int numberOfBytes = image.Length;
// put the size into an array
byte[] numberOfBytesArray = BitConverter.GetBytes(numberOfBytes);
// send the image size
nowystream.Write(numberOfBytesArray, 0, numberOfBytesArray.Length);
// send the image
nowystream.Write(image, 0, numberOfBytes);
Client part:
client = new TcpClient("127.0.0.1", 5000);
stream = client.GetStream();
byte[] data = new byte[4];
// read the size
stream.Read(data, 0, data.Length);
int size = BitConverter.ToInt32(data, 0);
label1.Text = size.ToString();
// prepare buffer
data = new byte[size];
// load image
stream.Read(data, 0, data.Length);
// save image to file for test
File.WriteAllBytes("received.jpg", data);
MemoryStream MS = new MemoryStream(data);
pictureBox1.Image = Image.FromStream(MS);
stream.Read doesn't guarantee that it will read data.Length bytes. Instead it returns number of bytes read. So you should check its return value and continue reading till you get all the bytes.
See http://msdn.microsoft.com/en-us/library/system.io.stream.read(v=vs.90).aspx (Section Return Value)
Thr read method can be something like this
void Read(Stream stream, byte[] buffer,int offset,int len)
{
int read = 0;
while (read < len)
{
read += stream.Read(buffer, offset + read, len-read);
}
}