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;
Related
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();
}
i want to send string json over networkstream . code at client side
using (var ns = new NetworkStream(socket))
{
string json = JsonConvert.SerializeObject(listCfile, Formatting.Indented);
byte[] jsonbytes = Encoding.UTF8.GetBytes(json);
byte[] jsonLength = BitConverter.GetBytes(jsonbytes.Length);
ns.Write(jsonLength, 0, jsonLength.Length);
ns.Write(jsonbytes, 0, jsonbytes.Length);
}
jsonbytes was byte[988324]
At server side
using (var ns = new NetworkStream(socket))
{
byte[] byDataLength = new byte[4];
ns.Read(byDataLength, 0, 4);
int jsonLength = BitConverter.ToInt32(byDataLength, 0);
byte[] byData = new byte[jsonLength];
ns.Read(byData, 0, jsonLength);
File.WriteAllBytes("E:\\json.txt",byData);
}
byData was byte[988324]
But byData i received isn't same as jsonbytes i sent.
i need some helps.
Update! some times it works. ByData received is same as jsonbytes i sent
Some times it doesn't work :(
You can try using raw sockets to send and receive as well as using a memory stream and end-of-packet mechanism for unknown data lengths.
Below is a snippet of methods showing using raw sockets and buffering in a memory-stream till End-Of-Packet is detected.
protected const int SIZE_RECEIVE_BUFFER = 1024; /// Receive buffer size
protected const string EOF = "!#~*|"; /// End of packet string
MemoryStream _msPacket = new MemoryStream(); /// Memory stream holding buffered data packets
int _delmtPtr = 0; /// Ranking pointer to check for EOF
Socket _baseSocket;
public event EventHandler OnReceived;
// TODO: -
// Add methods to connect or accept connections.
// When data is send to receiver, send with the same EOF defined above.
//
//
public void RegisterToReceive()
{
byte[] ReceiveBuffer = new byte[SIZE_RECEIVE_BUFFER];
_baseSocket.BeginReceive
(
ReceiveBuffer,
0,
ReceiveBuffer.Length,
SocketFlags.None,
new AsyncCallback(onReceiveData),
ReceiveBuffer
);
}
private void onReceiveData(IAsyncResult async)
{
try
{
byte[] buffer = (byte[])async.AsyncState;
int bytesCtr = 0;
try
{
if (_baseSocket != null)
bytesCtr = _baseSocket.EndReceive(async);
}
catch { }
if (bytesCtr > 0)
processReceivedData(buffer, bytesCtr);
RegisterToReceive();
}
catch{ }
}
private void processReceivedData(byte[] buffer, int bufferLength)
{
byte[] eof = Encoding.UTF8.GetBytes(EOF);
int packetStart = 0;
for (int i = 0; i < bufferLength; i++)
{
if (buffer[i].Equals(eof[_delmtPtr]))
{
_delmtPtr++;
if (_delmtPtr == eof.Length)
{
var lenToWrite = i - packetStart - (_delmtPtr - 1);
byte[] packet = new byte[lenToWrite + (int)_msPacket.Position];
if (lenToWrite > 0)
_msPacket.Write(buffer, packetStart, lenToWrite);
packetStart = i + 1;
_msPacket.Position = 0;
_msPacket.Read(packet, 0, packet.Length);
try
{
if (OnReceived != null)
OnReceived(packet, EventArgs.Empty);
}
catch { }
_msPacket.Position = 0;
_delmtPtr = 0;
}
}
else
{ _delmtPtr = 0; }
}
if (packetStart < bufferLength)
_msPacket.Write(buffer, packetStart, bufferLength - packetStart);
if (_msPacket.Position == 0)
_msPacket.SetLength(0);
}
This can receive large length of data and is independent of length by the sender.
The methods above shows how to receive data only, so will have to include other methods for connect, accept, sending-data, etc on raw sockets.
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
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.
I am trying to send files with a bunch of strings from Android client to C# server. The strings, among other things, will also contain details with regards to the file being sent eg: File Size, File Name, etc. The issue I am having is that all the file bytes is not received thus the original file cannot be reconstructed at the destination even though I can properly retrieve all the strings.
My C# Server Code
while (true)
{
Socket socket = listener.AcceptSocket();
setStatus(socket.RemoteEndPoint + " Connected");
try
{
// Open the stream
NetworkStream stream = new NetworkStream(socket);
System.IO.StreamReader sr = new StreamReader(stream);
//Get string data
//********************************************
Teststr = sr.ReadLine();
setStatus(Teststr);
FileSize = sr.ReadLine();
long fileSizeLong = Convert.ToInt64(FileSize);
int length = (int)fileSizeLong;
setStatus("File size: " + length + " bytes");
//********************************************
//read bytes to buffer
byte[] buffer = new byte[length];
int toRead = (int)length;
int read = 0;
while (toRead > 0)
{
int noChars = stream.Read(buffer, read, toRead);
read += noChars;
toRead -= noChars;
}
setStatus("File Recieved. Total bytes: " + Convert.ToString(buffer.Length));
setStatus("Saving File");
String recievedPath = "C:\\Test\\";
BinaryWriter bWrite = new BinaryWriter(File.Open(recievedPath + "Test.png", FileMode.Create));
bWrite.Write(buffer);
setStatus("File Saved to: " + recievedPath);
bWrite.Flush();
bWrite.Close();
stream.Flush();
stream.Close();
}
catch (Exception e)
{
setStatus(e.Message);
}
setStatus("Disconnected");
socket.Close();
}
My Android Client Code
File file = new File(configstr[2]); //create file instance
try {
client = new Socket(configstr[0], Integer.valueOf(configstr[1]));
//Read file
fileInputStream = new FileInputStream(file);
outputStream = client.getOutputStream();
//Output database details to stream
//*****************************************
//Holds the string before conversion to bytes
String text = "";
text = "Test\n";
outputStream.write(text.getBytes());
text = String.valueOf(file.length()) + "\n";
outputStream.write(text.getBytes());
//*****************************************
outputStream.flush();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
int bytesRead = 0;
while ((bytesRead = fileInputStream.read(b)) != -1) {
bos.write(b, 0, bytesRead);
}
byte[] bytes = bos.toByteArray();
outputStream.write(bytes);
outputStream.flush();
return true;
} catch (UnknownHostException e) {
e.printStackTrace();
return false;
} catch (IOException e) {
e.printStackTrace();
return false;
}
NOTE: The code works well if I only send one string, eg: If I only send file size.
Any better way of getting this to work as I am trying to send many strings through the stream as well as binary data from the file.
BufferedWriter with flush() at the end of every write() solved the issue for me.