Transformation an image file in tcp/ip - c#

I convert image file into a byte array and packetize it to 14-byte packets and send it via SerialPortEventHandler. on the other hand, in reciever part I lost some packets and when I generate recieved byte array in a new image file, the rest of the image, after the lost packet, shifted incorrectly, I have replaced lost packets with zero. while this works with text file perfectly. This is my code in client and server side:
client
_file = ofile.ConvertFileToByte(txtFileName.Text);
for (int k = 0; k < Configuration.PacketNumberInFrame; k++)
{
((BackgroundWorker)sender).ReportProgress((j * Configuration.PacketNumberInFrame + i) * 100 / Configuration.FileCount);
if (i + _numberOfByte <= Configuration.FileCount)
_packet = _file.SubArray(i, _numberOfByte);
}
//send packet
...
Server
try
{
while (true)
{
size = port.BytesToRead;
if (size >= 18)
break;
}
byte[] packet = new byte[size];
var str2 = port.Read(packet, 0, size);
if (System.Text.Encoding.Default.GetString(packet).Contains(Configuration.EndKeyByte) && !endFlag)
EndRecieving();
else
Extract(packet);
}
catch
(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
public Extract(packet)
{
Recieve_Data.Add( packet);
}
public EndRecieving()
{
for(int i=0;i< arrayResult.AddRange(packetData);i++)
{
arrayResult.AddRange(packetData);
}
string filePath = Configuration.LogFilePath + "\\CreatedFile-" + "."filePrefix.ToLower();
var stream = new FileStream(filePath,
FileMode.Create,
FileAccess.ReadWrite);
FileData oFile = new FileData();
stream.Write(result, 0, result.Length);
stream.Close();
}

Related

File size change when using TCP

I send a 4 MB file by tcp to the local server. But the file is stored at 36 MB on the local server.
What is the problem with?
I convert file to string (base64) and add to my json. then Convert json to byte[] and send it.
Client send byte to server:
await nwStream.WriteAsync(json, 0, json.Length);
NetworkStream streams = client.GetStream();
int Q = 0;
int M = json.Length;
int ss = 150001;
bool go = true;
while (go)
{
if(M< ss)
{
go = false;
ss = M;
}
if (M < 0)
{
go = false;
ss = M + ss;
}
await streams.WriteAsync(json, Q,ss);
Q += ss;
M -= ss;
}
and Server side get byte[]:
Byte[] bytes = new Byte[150001];
int i;
try
{
// Loop to receive all the data sent by the client.
while ((i = await stream.ReadAsync(bytes, 0, bytes.Length)) != 0)
{
// bytes contains received data in byte[].
// Translate data bytes to a UTF-8 string.
byte[] receivedBuffer = new byte[i];
Array.Copy(bytes, receivedBuffer, i);
data += System.Text.Encoding.UTF8.GetString(receivedBuffer);
if (data.IndexOf("}") > 0)
{
break;
}
}
}
catch (Exception ex)
{
}
Edit:
and Save File, I Encoding 'data' to UTF8 string, then convert to DeserializeObject.
var pi = Convert.FromBase64String(picbas64);
var x = (Bitmap)((new ImageConverter()).ConvertFrom(pi));
string path = #"pic\Operation\" + name + ".jpg";
var ZZ = x;
ZZ.Save(path);
return path;

Sending Hex string to TCP Socket

I am connecting VideoJet Printer to my PC using TCP/IP, creating C# windows dekstop application to read and write TCP Socket. When I am semding below Hex String using hercules software [When HEX Checkbox tick] it is responding but when I am sending same hex string from my C# code it is not reponding
Please suggest me where I am doing wrong in my code
try
{
client = new TcpClient("192.168.2.1", Convert.ToInt32("3001"));
// Translate the passed message into ASCII and store it as a Byte array.
Byte[] data = HexString2Bytes(richTextBox3.Text);
stream = client.GetStream();
// Send the message to the connected TcpServer.
stream.Write(data, 0, data.Length);
Console.WriteLine("Sent: {0}",richTextBox3.Text);
// Receive the TcpServer.response.
data = new Byte[65000];
var readStream = new MemoryStream();
int readBytes = stream.Read(data, 0, data.Length);
while (readBytes > 0)
{
readStream.Write(data, 0, readBytes);
readBytes = stream.Read(data, 0, data.Length);
}
var responseData = Encoding.ASCII.GetString(readStream.ToArray());
}
catch (Exception ex)
{
string errormsg = ex.ToString();
}
private byte[] HexString2Bytes(string hexString)
{
//check for null
if (hexString == null) return null;
//get length
int len = hexString.Length;
if (len % 2 == 1) return null;
int len_half = len / 2;
//create a byte array
byte[] bs = new byte[len_half];
try
{
//convert the hexstring to bytes
for (int i = 0; i != len_half; i++)
{
bs[i] = (byte)Int32.Parse(hexString.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber);
}
}
catch (Exception ex)
{
MessageBox.Show("Exception : " + ex.Message);
}
//return the byte array
return bs;
}
Command Hex String
A503CA002C000000E4411251C0000000B60000003C0050006100720061006D0073003E00200020003C0043006F006C002000690064003D00220044006500760069006300650073002F0050004800640073002F0031002F005000720069006E00740049006E0066006F0072006D006100740069006F006E002200200067006500740046006C006100670073003D002200320022002000670065007400440065007000740068003D0022002D003100220020002F003E003C002F0050006100720061006D0073003E000000
I actually don't know, why you have to make a While loop. when you received number of bytes from Server readBytes, so you could finish a code with Encoding like this:
string responseData = Encoding.ASCII.GetString(data,0,readbytes);
To get more information, you can find in this link https://learn.microsoft.com/en-us/dotnet/api/system.net.sockets.tcpclient?view=net-5.0

How can I make each flush() work, which make each buffer sent before next write() in C#

I am trying to sent very screenshot when i move the mouse on the screen. Therefore, I will sent the size of screenshot and image byte[]. In my client side, I will set the size byte array by the size received from server, and read the rest of byte[] as image. Ideally, I need each time I call the write(), the byte[] I want write into should be empty, so I use the flush(). In fact, after I received the getinputstream(), Sometime I will get the old data inside it. I don't know why flush() doesn't work. anyone has better ideas to solve this problem?
This is my code for server, I try use stream, and networkstream, it dosent works.
public void send(byte[] imageByte)
{
Stream stream = client.GetStream();
client.NoDelay = true;
client.Client.NoDelay = true;
Debug.WriteLine("noDelay:{0}, client.noDelay:{1}", client.NoDelay, client.Client.NoDelay);
byte[] imageSize;
string imgSize = Convert.ToString(imageByte.Length);
Debug.WriteLine("string=" + imgSize);
imageSize = Encoding.ASCII.GetBytes(imgSize);
Debug.WriteLine(" header size:" + imageSize.Length);
//ns.Write(imageSize, 0, imageSize.Length);
//ns.Flush();
//sleep 500 ms
stream.Write(imageSize, 0, imageSize.Length);
stream.Flush();
Thread.Sleep(150);
Debug.WriteLine("sent size");
//ns.Write(imageByte, 0, imageByte.Length);
//ns.Flush();
stream.Write(imageByte, 0, imageByte.Length);
stream.Flush();
Debug.WriteLine("First time sent image size:" + imageByte.Length);
client side:
public class connection extends AsyncTask {
private byte[] data;
public void setByteSize(int size) {
data = new byte[size];
}
public byte[] getByteSize() {
return data;
}
#Override
protected Object doInBackground(Object... arg0) {
try {
clientSocket = new Socket("134.129.125.126", 8080);
// clientSocket = new Socket("134.129.125.172", 8080);
System.out.println("client connect to server");
input = clientSocket.getInputStream();
System.out.println("getinputstream");
} catch (UnknownHostException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
while (true) {
int totalBytesRead = 0;
int chunkSize = 0;
int tempRead = 0;
String msg = null;
// byte[] data = null;
byte[] tempByte = new byte[1024 * 1024 * 4];
try {
// read from the inputstream
tempRead = input.read(tempByte);
// tempbyte has x+5 byte
System.out.println("Fist time read:" + tempRead);
// convert x+5 byte into String
String message = new String(tempByte, 0, tempRead);
msg = message.substring(0, 5);
int msgSize = Integer.parseInt(msg);
data = new byte[msgSize];
// for(int i =0;i<tempRead-5;i++)
// {
// data[i]=tempByte[i+5];
// }
for (int i = 0; i < msgSize; i++) {
data[i] = tempByte[i + 5];
}
// cut the header into imageMsg
// String imageMsg = new String(tempByte, 5, tempRead - 5);
// convert string into byte
System.out.println("message head:" + msg);
byteSize = Integer.parseInt(msg);
System.out.println("ByteSize:" + byteSize);
// convert String into byte[]
totalBytesRead = tempRead - 5;
System.out.println("total Byte Read=" + totalBytesRead);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
// get string for the size of image
try {
while (totalBytesRead != getByteSize().length) {
System.out.println("data length:"
+ getByteSize().length);
chunkSize = input.read(getByteSize(), totalBytesRead,
getByteSize().length - totalBytesRead);
System.out.println("chunkSize is " + chunkSize);
totalBytesRead += chunkSize;
// System.out.println("Total byte read "
// + totalBytesRead);
}
System.out.println("Complete reading - total read = "
+ totalBytesRead);
} catch (Exception e) {
}
bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
System.out.println("deco");
runOnUiThread(new Runnable() {
public void run() {
image.setImageBitmap(bitmap);
System.out.println("setImage at less than 500");
}
});
}
}
}

Transferring files through sockets (bir and small sized)

Hello I'm trying to implement a server and client couple that can transfer files of any kind and any size but there is a problem I somehow corrupt files. I tried lots of methods but can't figure it out. So basicly I can connect ,I can understand which file does client want, and can send it through sockets. When I try to open that file it shows me an error message(Tried winrar, mp4, avi files) Here is my code:
//Server
private void Receive(string receivedFileName, string fileSize)
{
try
{
int receivedBytesLen = 0;
byte[] incomingFile = new byte[int.Parse(fileSize)];
activity.AppendText("Preparing to download... \n");
while (incomingFile != null && int.Parse(fileSize) > receivedBytesLen)
{
tempSocket.Receive(incomingFile);
receivedBytesLen = incomingFile.Length;
int fileNameLen = BitConverter.ToInt32(incomingFile, 0);
File.WriteAllBytes(fileDir + "//" + receivedFileName, incomingFile);
}
activity.AppendText("File saved to " + fileDir + "\n");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
//////////////////////////////////////////////////////////////////////
//server option 2
private void Receive(string receivedFileName, string fileSize)
{
try
{
byte[] incomingFile = new byte[10124 * 5000];
activity.AppendText("Preparing to download... \n");
BinaryWriter bWrite = new BinaryWriter(File.Open(folderBrowserDialog1.SelectedPath + "//" + receivedFileName, FileMode.Append));
int receivedBytesLen = tempSocket.Receive(incomingFile, incomingFile.Length, 0);
int fileNameLen = BitConverter.ToInt32(incomingFile, 0);
//string fileName = Encoding.UTF8.GetString(incomingFile, 4, fileNameLen);
//bWrite.Write(incomingFile, 4 + fileNameLen, receivedBytesLen - 4 - fileNameLen);
while (receivedBytesLen > 0)
{
receivedBytesLen = tempSocket.Receive(incomingFile, incomingFile.Length, 0);
if (receivedBytesLen == 0)
{
bWrite.Close();
}
else
{
bWrite.Write(incomingFile, 0, receivedBytesLen);
}
}
activity.AppendText("File saved to " + fileDir + "\n");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
/////////////////////////////////////////////////////////////////////
//client
private void Upload_Click(object sender, EventArgs e)
{//Uploads selected file after clicking upload button.
try
{
if (clientSocket.Connected)
{
byte[] buffer = new byte[1024];
byte[] sendingFile = null;
sendingFile = File.ReadAllBytes(openFileDialog1.FileName);
FileInfo f = new FileInfo(openFileDialog1.FileName);
string fileSize = f.Length.ToString();
buffer = Encoding.Default.GetBytes(getUserName.Text + "Upload" + openFileDialog1.SafeFileName + "size" + fileSize + "end");
clientSocket.Send(buffer);
activityLog.AppendText("Sending File \n");
int bytesToBeSent = sendingFile.Length;
int bytesActuallySent = 0;
while(bytesActuallySent < bytesToBeSent){
bytesActuallySent += clientSocket.Send(sendingFile, bytesActuallySent, bytesToBeSent -bytesActuallySent, 0);
}
activityLog.AppendText("File Sent.\n");
}
}
catch(Exception ex){
MessageBox.Show(ex.Message);
}
}
server option #2 is better. But there are some improvements
socket receive buffer is limited decided by OS, generally is 8192
use FileStream in client and server and do not forget to close filestream after file download
client:
FileStream fileStream = new FileStream(filePath, FileMode.Open)
byte[] buff = new byte[8192];
do
{
bytesRead = fileStream.Read(buff, 0, buff.Length);
sock.send(dataSock, buff, bytesRead);
}while (bytesRead > 0);
fileStream.close();
server:
FileStream fileStream = new FileStream(filePath, FileMode.Open)
do
{
bytesRead = sock.receive(buff, 0, buff.Lenght);
fileStream.Write(buff, 0, bytesRead );
}while (bytesRead > 0);
fileStream.close();
In order to satisfy ANY sized file you need an option #3, one that reads a block of bytes til all bytes are received, your option #1 wouldn't do so well on a 3 GIG file running on 2 GIG box...
Here is a link: http://www.yoda.arachsys.com/csharp/readbinary.html
I like option #2 from this link.
However in the example they write to a memoryStream, you should write to a filestream, the target file.

I cant receive anything other than text files

I have tried every solution I could find but nothing seems to work. Anything other than text files becomes corrupted; someone said that TCP can't send more than 8KB, so I tried to fix the problem and I think I did. Now, when I send a text file (no matter what size it is), it reaches perfectly but anything else gets corrupted. I know the code for the cutting is expensive to performance but I am going to think about that later.
Here is my sender code:
private string SendFile(string tosend, string tosendname)
{
ipadd = IPAddress.Parse(textBox2.Text);
ep = new IPEndPoint(ipadd, 6112);
Sender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
Sender.Connect(ep);
Thread.Sleep(100);
byte[] filetosend = System.IO.File.ReadAllBytes(tosend);
FileStream fs = new FileStream(tosend, FileMode.Open, FileAccess.Read);
//Read byte from image
fs.Read(filetosend, 0, filetosend.Length);
fs.Flush();
fs.Close();
int countt = filetosend.Count();
int dividedcount = countt / 7000;
Sender.Send(Encoding.ASCII.GetBytes("filesize#" + filetosend.Count().ToString()));
Thread.Sleep(500);
List<byte> cuttedtosend = new List<byte>();
for (int counti = 0; counti < dividedcount; counti++)
{
cuttedtosend = new List<byte>();
for (int index = 0; index < 7000; index++)
{
cuttedtosend.Add(filetosend[(filetosend.Count() - countt) + index]);
}
Sender.Send(cuttedtosend.ToArray());
Thread.Sleep(100);
countt -= 7000;
richTextBox1.Invoke((MethodInvoker)delegate { richTextBox1.AppendText("Countt = " + countt + "\n"); });
richTextBox1.Invoke((MethodInvoker)delegate { richTextBox1.AppendText("Counti = " + counti + "\n"); });
}
richTextBox1.Invoke((MethodInvoker)delegate { richTextBox1.AppendText("Done"); });
cuttedtosend = new List<byte>();
for (int index = filetosend.Count() - countt; index < filetosend.Count(); index++)
{
//richTextBox1.Invoke((MethodInvoker)delegate { richTextBox1.AppendText(index + "this is 2 \n"); });
cuttedtosend.Add(filetosend[index]);
}
Sender.Send(cuttedtosend.ToArray());
countt -= countt;
return "";
}
And here is my receive code:
private async void StartReceiving()
{
List<byte> neededbytes = new List<byte>();
receivedbyte = new byte[InputForm.s];
Receiver.Bind(new IPEndPoint(IPAddress.Parse("0"), 6112));
Receiver.Listen(1000);
string filename = "Downloadedfile";
bool cont = false;
while (true)
{
Client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
Client = Receiver.Accept();
int filesize = 0;
byte[] receivechecker = new byte[100];
Client.Receive(receivechecker);
if(Encoding.ASCII.GetString(receivechecker).Contains("filesize#"))
{
filesize = Convert.ToInt32(Encoding.ASCII.GetString(receivechecker).Remove(0, 9));
Client.Receive(receivechecker);
}
if (Encoding.ASCII.GetString(receivechecker).Contains("#100254#"))
{
string[] splttedtext = Encoding.ASCII.GetString(receivechecker.ToArray()).Split('#');
if (splttedtext[0] == "mess")
{
MessageBox.Show(splttedtext[2]);
}
else if (splttedtext[0] == "filename")
{
//MessageBox.Show(splttedtext[2]);
filename = splttedtext[2];
//filename.Replace(#"\", #"/");
cont = true;
}
}
else
{
List<byte> tosave = new List<byte>();
richTextBox1.Invoke((MethodInvoker)delegate { richTextBox1.AppendText(filesize.ToString() + "\n"); });
int countt = filesize / 7000;
FileStream writer = File.Create("DownloadedFile.jpg");
for (int counti = 0; counti < countt; counti++)
{
byte[] toadd = new byte[7000];
richTextBox1.Invoke((MethodInvoker)delegate { richTextBox1.AppendText("Counti = " + counti.ToString() + "\n"); });
Client.Receive(toadd);
writer.Write(toadd,0,toadd.Count());
neededbytes.AddRange(toadd);
filesize -= 7000;
}
richTextBox1.Invoke((MethodInvoker)delegate { richTextBox1.AppendText(filesize.ToString() + "\n"); });
byte[] toadds = new byte[filesize];
Client.Receive(toadds);
writer.Write(toadds,0,toadds.Count());
writer.Close();
neededbytes.AddRange(toadds);
filesize -= filesize;
}
}
Thanks in advance :D
Edit:
I just tried Sending a 7mb text file and it reached complete.......
The most immediate problem is that you're saving bytes that you didn't necessarily receive. For example, you have:
for (int counti = 0; counti < countt; counti++)
{
byte[] toadd = new byte[7000];
richTextBox1.Invoke((MethodInvoker)delegate { richTextBox1.AppendText("Counti = " + counti.ToString() + "\n"); });
Client.Receive(toadd);
writer.Write(toadd,0,toadd.Count());
neededbytes.AddRange(toadd);
filesize -= 7000;
}
The documentation for Receive says that the method will receive up to the number of bytes you request. It's not uncommon for it to return fewer bytes than you requested, especially at the end of the file (since it couldn't receive more than the file length).
You need to write:
var bytesRead = Client.Receive(toadd);
writer.Write(toadd, 0, bytesRead); // only write as many bytes as you've read
In general, your code is pretty convoluted, and you have several other possible problems just waiting to bite you. For example, the code that sends the file size sleeps for 500 ms, which just happens to be enough time for the receiver to read just the number of bytes sent. Without that sleep, your code would fail.
You have code to receive the file name, but no code to send it.
I would suggest that you eliminate the ASCII tags and send things in binary. Below is your rewritten Send method.
private string SendFile(string tosend, string tosendname)
{
ipadd = IPAddress.Parse(textBox2.Text);
ep = new IPEndPoint(ipadd, 6112);
Sender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
Sender.Connect(ep);
byte[] filetosend = System.IO.File.ReadAllBytes(tosend);
byte[] filesizeBytes = BitConverter.GetBytes(filetosend.Length);
Sender.Send(filesizeBytes); // sends the length as an integer
// note: You could use Socket.Send(filetosend) here.
// but I'll show an example of sending in chunks.
int totalBytesSent = 0;
while (totalBytesSent < filetosend.Length)
{
int bytesLeft = filetosend.Length - totalBytesSent;
int bytesToSend = Math.Min(bytesLeft, 7000);
Sender.Send(filetosend, totalBytesSent, bytesToSend);
richTextBox1.Invoke((MethodInvoker)delegate
{ richTextBox1.Append(totalBytesSent + " bytes sent\n"); });
totalBytesSent += bytesToSend;
}
richTextBox1.Invoke((MethodInvoker)delegate { richTextBox1.AppendText("Done"); });
return "";
}
The receiver code is similarly simplified:
private async void StartReceiving()
{
Receiver.Bind(new IPEndPoint(IPAddress.Parse("0"), 6112));
Receiver.Listen(1000);
string filename = "Downloadedfile";
bool cont = false;
while (true)
{
Client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
Client = Receiver.Accept();
// read the length
byte[] filesizeBytes = new byte[4];
int totalBytesReceived = 0;
while (totalBytesReceived < 4)
{
int bytesRead = Client.Receive(
filesizeBytes, totalBytesReceived, 4-totalBytesReceived);
totalBytesReceived += bytesRead;
}
int filesize = BitConverter.ToInt32(filesizeBytes);
richTextBox1.Invoke((MethodInvoker)delegate
{ richTextBox1.AppendText(filesize.ToString() + "\n"); });
// now read the file
using (FileStream writer = File.Create("DownloadedFile.jpg"))
{
byte[] readBuffer = new byte[7000];
totalBytesReceived = 0;
while (totalBytesReceived < filesize)
{
int bytesToRead = Math.Min(7000, filesize - totalBytesReceived);
int bytesRead = Client.Receive(readBuffer, 0, bytesToRead);
totalBytesRead += bytesRead;
writer.Write(readBuffer, 0, bytesRead);
richTextBox1.Invoke((MethodInvoker)delegate
{ richTextBox1.AppendText("Read " + bytesRead.ToString() + "bytes\n"); });
}
richTextBox1.Invoke((MethodInvoker)delegate
{ richTextBox1.AppendText("Done. " + totalBytesRead.ToString() + " bytes\n"); });
}
}
If you want to send the file name, then I would suggest converting it to UTF8 (Encoding.UTF8.GetBytes(filename)), then send an int (4 bytes) that says how long it is, and then the buffer. To receive it, read the 4-byte filename length like I showed how to read the file size, then that many bytes for the file name, and convert back to a string (Encoding.UTF8.GetString(bytes, 0, filenameLength)).
Please excuse any typos or minor errors in the code. I'm doing this from memory and trying to keep somewhat with your coding style.
i suspect that you are expecting the same blocks that you send to be received; ie that record boundaries will be preserved. This is not so. TCP guarantees that every byte sent will be received and that order is preserved; but you could do 1 large 10k send and receive 10k 1 byte messages.

Categories