I am using network stream to send a file name (example :"text.txt") and then send the file. the server is supposed to read the name and create a write stream to write the data in. the problem that the server gets the name + data from the file in the read command to get the name only. i think this is unclear.
the question i get the file name + some data from the file.
code that sends file name then file data:
ASCIIEncoding asci = new ASCIIEncoding();
TcpClient clientSocket = new TcpClient(textBox2.Text, 8880);
NetworkStream networkStream = clientSocket.GetStream();
byte[] b = asci.GetBytes(s);//s is the name of the file
networkStream.Write(b, 0, b.Length);
networkStream.Flush();
while(true)
{
file = fileStream.Read(fileBuffer,0,fileBuffer.Length);
networkStream.Write(fileBuffer,0,file);
if(file == 0) break;
}
the code that the server rec. the name and data with
byte [] buffer2 = new byte[1];
String filename = "";
ASCIIEncoding asci = new ASCIIEncoding();
while (true)
{
int k = networkStream.Read(buffer2, 0, buffer2.Length);
filename = filename+asci.GetString(buffer2, 0, k);
if (k == 0) break;
}
using (Stream fileStream = File.OpenWrite("C:/Users/Laptop/Documents/" + filename))
{
while (true)
{
thisRead = networkStream.Read(dataByte, 0, blockSize);
fileStream.Write(dataByte, 0, thisRead);
if (thisRead == 0) break;
}
thanks. i think i dont know how to say or illustrate the problem.
You have to send something that indicates the end of the filename. The server receives the filename as long as this or these stop characters are not received and it receives the payload afterwards.
For example, HTTP uses \r\n\r\n to mark the end of the HTTP header.
Related
I have one question regarding to the way of sending file and receiving file in C# language. I have created a simple file transfer windows form application but it only supports with .txt file format. If I try to send an image file or ms words document file, it could be completely received at the receiving side. But, the received file is unreadable and cannot be opened. I have done a similar application Java but it works for any file format and I am using the same logic to implement in the C# application. Can anyone give me some suggestion or advices on this?
SENDING SIDE:
// establish connection
int port = Convert.ToInt32(txtLocalPort.Text) - 5;
TcpListener listener = new TcpListener(IPAddress.Parse(txtLocalIP.Text), port);
listener.Start();
// get file size
byte[] data = File.ReadAllBytes(downFile);
int fSize = data.Length;
// calculate block numbers, 1024 bytes each block
int block = fSize / 1024;
// leftover file bytes, less than 1024 bytes
int byteLeft = fSize % 1024;
// convert String to byte
String cmd = "SEND_FILE" + fSize.ToString();
buff = new byte[1024];
buff = Encoding.ASCII.GetBytes(cmd);
// send message in byte
msgSocket.Send(buff);
// accept connection
TcpClient client = listener.AcceptTcpClient();
// remote host connected
if (client.Connected == true)
{
// medium to read file bytes from file chosen
BinaryReader readByte = new BinaryReader(File.Open(downFile, FileMode.Open));
// medium to send file bytes
NetworkStream dataOUT = client.GetStream();
// send file bytes based on calculated block numbers
for (int i = 0; i < block; i++)
{
// buffer size
buff = new byte[1024];
// read file bytes from file chosen
readByte.Read(buff, 0, buff.Length);
// send file bytes
dataOUT.Write(buff, 0, buff.Length);
dataOUT.Flush();
}
// leftover file bytes
// buffer size
buffLeft = new byte[byteLeft];
// read leftover file bytes from file chosen
readByte.Read(buffLeft, 0, buffLeft.Length);
// send leftover file bytes
dataOUT.Write(buff, 0, buffLeft.Length);
dataOUT.Flush();
MessageBox.Show("File sent successfully.", "File Share", MessageBoxButtons.OK, MessageBoxIcon.Information);
// close the medium
readByte.Close();
dataOUT.Close();
client.Close();
listener.Stop();
RECEIVING SIDE:
// establish connection
int port = Convert.ToInt32(txtRemotePort.Text) - 5;
TcpClient client = new TcpClient(Dns.GetHostEntry(IPAddress.Parse(txtRemoteIP.Text)).HostName.ToString(), port);
// connected to remote host
if (client.Connected == true)
{
// get invalid character
String invalid = new String(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars());
// remove invalid character
foreach (char c in invalid)
{
fileName = fileName.Replace(c.ToString(), "");
}
String downFile = Path.Combine(#"D:\", fileName);
// file size
int fSize = fileSize;
// calculate block numbers, 1024 bytes each block
int block = fSize / 1024;
// leftover file bytes, less than 1024 bytes
int byteLeft = fSize % 1024;
// medium to receive file bytes
NetworkStream dataIN = client.GetStream();
// medium to write file bytes to new file
BinaryWriter writeByte = new BinaryWriter(File.Open(downFile, FileMode.Create));
// receive file bytes based on calculated block numbers
for (int i = 0; i < block; i++)
{
// buffer size
buff = new byte[1024];
// receive file bytes
dataIN.Read(buff, 0, buff.Length);
dataIN.Flush();
// write file bytes to new file
writeByte.Write(buff, 0, buff.Length);
writeByte.Flush();
}
// receive leftover file bytes
// buffer size
buffLeft = new byte[byteLeft];
// receive file bytes
dataIN.Read(buffLeft, 0, buffLeft.Length);
dataIN.Flush();
// write file bytes to new file
writeByte.Write(buffLeft, 0, buffLeft.Length);
writeByte.Flush();
MessageBox.Show("File downloaded successfully.", "File Share", MessageBoxButtons.OK, MessageBoxIcon.Information);
// close the medium
writeByte.Close();
dataIN.Close();
client.Close();
I think I've found out what you did wrong:
Instead of
BinaryWriter writeByte = new BinaryWriter(File.Open(downFile, FileMode.Create));
Use
BinaryWriter writeByte = new BinaryWriter(File.Open(downFile, FileMode.Append));
I have a Microscan TCP/IP barcode reader. I am currently using the following code to connect to it and retrieve a barcode when read:
// responseData string will be the barcode received from reader
string responseData = null;
TcpClient client = new TcpClient("10.90.10.36", 2001);
// The "getData" is just a generic string to initiate connection
Byte[] sentData = System.Text.Encoding.ASCII.GetBytes("getData");
NetworkStream stream = client.GetStream();
stream.Write(sentData, 0, sentData.Length);
Byte[] receivedData = new Byte[20];
Int32 bytes = stream.Read(receivedData, 0, receivedData.Length);
for (int i = 0; i < bytes; i++)
{
responseData += Convert.ToChar(receivedData[i]);
}
// Closes the socket connection.
client.Close();
The issue that I am having is that I am only getting 10 characters when the barcode is 15. Everything works correctly until the Int32 bytes = stream.Read(receivedData, 0 receivedData.Length); line. The Read call is returning 10 rather than 15 as it should be. I have tried modifying the code in a few different ways, but all of them have just returned 10 characters like normal. This works correctly if the barcode is 10 characters or fewer, but not if more.
I don't think it's an issue with the scanner, but I am checking into that as well. Anyone have any ideas?
Try something like:
// responseData string will be the barcode received from reader
string responseData = null;
using (TcpClient client = new TcpClient("10.90.10.36", 2001))
{
using (NetworkStream stream = client.GetStream())
{
byte[] sentData = System.Text.Encoding.ASCII.GetBytes("getData");
stream.Write(sentData, 0, sentData.Length);
byte[] buffer = new byte[32];
int bytes;
while ((bytes = stream.Read(buffer, 0, buffer.Length)) != 0)
{
for (int i = 0; i < bytes; i++)
{
responseData += (char)buffer[i];
}
}
}
}
The while cycle will repeat itself while there are new characters that can be received. I have even put some using around your code (it's better to use them instead of Closeing manually objects)
I'm trying to send a couple of data via Sockets, so it's converted to bytes and then back to String on the Server. But I can only do one apparently.
Server code:
static void Read(IAsyncResult ar)
{
int fileNameLen = 1;
//int userNameLen = 9;
State newState = (State)ar.AsyncState; //gets state of Socket
Socket handler = newState.Socket_w; //passes Socket to handler
int bytesRead = handler.EndReceive(ar); //terminates Data Receive from Socket.
if (bytesRead > 0)
{
if (flag == 0)
{
fileNameLen = BitConverter.ToInt32(newState.buffer, 0); //gets filename length
fileName = Encoding.UTF8.GetString(newState.buffer, 4, fileNameLen); //gets filename
//userNameLen = BitConverter.ToInt32(newState.buffer, 8);
//getUsername = Encoding.UTF8.GetString(newState.buffer, 8, fileNameLen);
flag++;
}
}
}
Client code:
internal static void uploadFile(string host, string username, string getGame, string filename, string filepath)
{
byte[] m_clientData;
Socket clientSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
byte[] fileName = Encoding.UTF8.GetBytes(username + "_" + filename);
byte[] fileData = File.ReadAllBytes(filepath);
byte[] fileNameLen = BitConverter.GetBytes(fileName.Length);
//byte[] sendUsername = Encoding.UTF8.GetBytes(username);
//byte[] sendUsernameLen = BitConverter.GetBytes(sendUsername.Length);
//byte[] sendGame = Encoding.UTF8.GetBytes(getGame);
//byte[] sendGameLen = BitConverter.GetBytes(sendGame.Length);
m_clientData = new byte[4 + fileName.Length + fileData.Length];
fileNameLen.CopyTo(m_clientData, 0);
fileName.CopyTo(m_clientData, 4);
fileData.CopyTo(m_clientData, 4 + fileName.Length);
//sendUsernameLen.CopyTo(m_clientData, 0);
//sendUsername.CopyTo(m_clientData, 4);
//sendGameLen.CopyTo(m_clientData, 0);
//sendGame.CopyTo(m_clientData, 4);
clientSock.Connect(host, 8889);
clientSock.Send(m_clientData); //tofix exception
clientSock.Close();
}
I can't seem to decrypt it properly over on Server. Can anyone help me with the buffersizes and whatnot?
Read does not know anything about what was sent; TCP is basically just a stream - so there is absolutely nothing to say that you have all the data in one call to Read; you could have:
exactly the amount of data you sent
part of one message
17 messages
the end of one message and the start of the next
1 solitary byte from a message
You need to devise some kind of framing protocol that lets the receiver know when they have an entire message. That could be as simple as a length prefix, or can be more complex. You should then buffer the data in memory (or process it gradually) until you have the entire message. One call to Read is very unlikely to represent a single and complete message. Indeed, this is guaranteed not to be the case if a message is larger than your newstate.buffer, but you can get the same result even for small messages and a large buffer.
Can anyone give me a small tutorial on how to send file from java server to c# client and on receive complete acknowledgment message from c# to java. Actually I'm new to C# and dont know how to do socket programming. I'm stuck in it since long. Tried many codes. Some codes receive incomplete files some stuck in infinite loop. Please help me in this regard.
Thanks
EDIT
Here is what I have tried:
C# Server:
{
IPAddress ipAd = IPAddress.Parse("192.168.1.131");
// use local m/c IP address, and
// use the same in the client
/* Initializes the Listener */
TcpListener myList = new TcpListener(ipAd, 5600);
/* Start Listeneting at the specified port */
myList.Start();
Console.WriteLine("The server is running at port 5600...");
Console.WriteLine("The local End point is :" +
myList.LocalEndpoint);
Console.WriteLine("Waiting for a connection.....");
m:
clientSock = myList.AcceptSocket();
//clientSock.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.ReceiveTimeout,10000);
Console.WriteLine("Connection accepted from " + clientSock.RemoteEndPoint);
//byte[] b = new byte[100];
//int k = clientSock.Receive(b);
string fileName = "hello.wav";
NetworkStream networkStream = new NetworkStream(clientSock);
StreamReader sr = new StreamReader(networkStream);
//read file length
int length = int.Parse(sr.ReadLine());
if (networkStream.CanRead)
{
BinaryWriter bWrite = new BinaryWriter(File.Open(receivedPath + fileName, FileMode.Create));
int receivedBytesLen = -1;
byte[] clientData = new byte[4096 * 5000];
receivedBytesLen = networkStream.Read(clientData, 0, clientData.Length);
bWrite.Write(clientData, 0, receivedBytesLen);
do
{
receivedBytesLen = networkStream.Read(clientData, 0,clientData .Length);
bWrite.Write(clientData, 0, receivedBytesLen);
} while (receivedBytesLen > 0);
bWrite.Close();
networkStream.Close();
}
Console.WriteLine("Client:{0} connected & File {1} started received.", clientSock.RemoteEndPoint, fileName);
Console.WriteLine("File: {0} received & saved at path: {1}", fileName, receivedPath);
Recognizer_2 recognizeVoice = new Recognizer_2(clientSock);
recognizeVoice.recognize_wav(); // Acknowledgement
Console.WriteLine("\nResult Sent to the Client");
goto m;
}
Java Client:
Socket socket = new Socket("192.168.1.131", 5600);
BufferedReader response_Stream = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
File f = new File(mFileName);
byte[] buffer = new byte[(int) f.length()];
FileInputStream fis = new FileInputStream(f);
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read(buffer, 0, buffer.length);
OutputStream outputStream = socket.getOutputStream();
outputStream.write(buffer);
outputStream.flush();
String final_Result_String = "";
if (response_Stream != null) {
String respose_text = "";
while ((respose_text = response_Stream.readLine()) != null) {
final_Result_String += respose_text;
}
}
Toast.makeText(getApplicationContext(), final_Result_String, 1)
.show();
outputStream.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
There is no dependance between the languages used by the server or the client.
Just the structure of the data is important !
You should search for some tutorials on socket programming with C#.
For example: http://www.codeproject.com/Articles/10649/An-Introduction-to-Socket-Programming-in-NET-using
But the language doesn't matter, understand how the data is formatted when sent on the network.
Edit: you should add a byte or two in the data indicating the length of it. It's not because you dont have data to read once that all the data has been received.
I have been working on this application that enables user to log in into another website, and then download specified file from that server. So far I have succeeded in logging on the website and download the file. But everything ruins when it comes to zip files.
Is there any chunk of code that could be helpful in reading the .zip files byte by byte or by using stream reader?
I m using downloadfile() but its not returning the correct zip file.
I need a method by which I can read zip files. Can I do it by using ByteReader()
The code used to download zip file is
string filename = "13572_BranchInformationReport_2012-05-22.zip";
string filepath = "C:\\Documents and Settings\\user\\Desktop\\" + filename.ToString();
WebClient client = new WebClient();
string user = "abcd", pass = "password";
client.Credentials = new NetworkCredential(user, pass);
client.Encoding = System.Text.Encoding.UTF8;
try
{
client.DownloadFile("https://web.site/archive/13572_BranchInformationReport_2012-05-22.zip", filepath);
Response.Write("Success");
}
catch (Exception ue)
{
Response.Write(ue.Message);
}
Thanks in advance.
is there any chunk of code that could be helpful in reading the zip files bytes by bytes aur by using stream reader.
Absolutely not. StreamReader - and indeed any TextReader is for reading text content, not binary content. A zip file is not text - it's composed of bytes, not characters.
If you're reading binary content such as zip files, you should be using a Stream rather than a TextReader of any kind.
Note that WebClient.DownloadFile and WebClient.DownloadData can generally make things easier for downloading binary content.
Another simple way to downlaod zip file
<asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl="~/DOWNLOAD/Filename.zip">Click To Download</asp:HyperLink>
Another solution
private void DownloadFile()
{
string getPath = "DOWNLOAD/FileName.zip";
System.IO.Stream iStream = null;
byte[] buffer = new Byte[1024];
// Length of the file:
int length;
// Total bytes to read:
long dataToRead;
// Identify the file to download including its path.
string filepath = Server.MapPath(getPath);
// Identify the file name.
string filename = System.IO.Path.GetFileName(filepath);
try
{
// Open the file.
iStream = new System.IO.FileStream(filepath, System.IO.FileMode.Open,
System.IO.FileAccess.Read, System.IO.FileShare.Read);
// Total bytes to read:
dataToRead = iStream.Length;
// Page.Response.ContentType = "application/vnd.android.package-archive";
// Page.Response.ContentType = "application/octet-stream";
Page.Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);
// Read the bytes.
while (dataToRead > 0)
{
// Verify that the client is connected.
if (Response.IsClientConnected)
{
// Read the data in buffer.
length = iStream.Read(buffer, 0, 1024);
// Write the data to the current output stream.
Page.Response.OutputStream.Write(buffer, 0, length);
// Flush the data to the HTML output.
Page.Response.Flush();
// buffer = new Byte[1024];
dataToRead = dataToRead - length;
}
else
{
//prevent infinite loop if user disconnects
dataToRead = -1;
}
}
}
catch (Exception ex)
{
// Trap the error, if any.
Page.Response.Write(ex.Message);
}
finally
{
if (iStream != null)
{
//Close the file.
iStream.Close();
Page.Response.Close();
}
}
}
Your answer
WebRequest objRequest = System.Net.HttpWebRequest.Create(url);
objResponse = objRequest.GetResponse();
byte[] buffer = new byte[32768];
using (Stream input = objResponse.GetResponseStream())
{
using (FileStream output = new FileStream ("test.doc",
FileMode.CreateNew))
{
int bytesRead;
while ( (bytesRead=input.Read (buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, bytesRead);
}
}
}
This is how i achieved it. Thanks everyone for ur help