In my job I have server and clients (several devices) connected in to the same network.
Clients contacts with server using their web-browser.
Server is running a C# program that uses TcpListener to receive requests from browsers.
I'm trying to send an image through TcpClientto client device but this is the result:
I'v tried:
Read image file as String
Read image file as Byte[]
After some searches inside Chrome Developer console i found an error
net::ERR_CONTENT_LENGTH_MISMATCH.
i don't know why Content-Length: length-in-byte value isn't correct even through new FileInfo(Target).Length.
Code I use:
TcpListener Listener = new TcpListener(local_address, 9090);
Listener.Start();
TcpClient client = Listener.AcceptTcpClient();
NetworkStream ns = client.GetStream();
string target = HeaderKeys.GetValue("target"); /* image file in the request*/
string mime_type = MimeType.Extract(target); /* mime-type of the file */
byte[] content = File.ReadAllBytes(target);
StreamWriter writer = new StreamWriter(ns);
// response header
writer.Write("HTTP/1.0 200 OK");
writer.Write(Environment.NewLine);
writer.Write($"Content-Type: {mime_type}");
writer.Write(Environment.NewLine);
writer.Write("Content-Length: " + content.Length);
writer.Write(Environment.NewLine);
writer.Write(Environment.NewLine);
writer.Write(content);
writer.Flush();
client.Close();
I'v tried
NetworkStream directly.
reading image file in MemoryStream and NetworkStream to write.
reading image file as byte[] and convert it to Base64.
The issue was because of StreamWriter
I've solved the issue using this code:
TcpClient client = Listener.AcceptTcpClient();
Stream s = client.GetStream();
byte[] file_content = File.ReadAllBytes(file);
StringBuilder header = new StringBuilder();
header.Append("HTTP/1.1 200 OK\r\n");
header.Append($"Content-Type: {mime_type}\r\n");
header.Append($"Content-Length: {file_content .Length}\r\n\n");
byte[] h = Encoding.ASCII.GetBytes(header.ToString());
s.Write(content, 0, content.Length);
s.Write(b, 0, b.Length);
s.Flush();
client.Close();
Related
I am sending very large file over TCP/IP network which is working as expected.
Just one concern that how to send it efficiently so that memory consumption should be optimized.
Below is the working code
Stream fileStream = File.OpenRead(tbFilename.Text);
byte[] fileBuffer = new byte[fileStream.Length];
fileStream.Read(fileBuffer, 0, (int)fileStream.Length);
// Open a TCP/IP Connection and send the data
TcpClient clientSocket = new TcpClient(tbServer.Text,8080);
NetworkStream networkStream = clientSocket.GetStream();
networkStream.Write(fileBuffer,0,fileBuffer.GetLength(0));
networkStream.Close();
Firstly, Stream.Read will probably not read the whole file just a chunk, but you omit the return value, which is the number of read bytes.
Secondly, you should use a smaller buffer (eg. 4K) and use that to send the file.
const int BUFSIZE = 4096;
long transferred = 0L;
long length = fileStream.Length;
using (BinaryReader br = new BinaryReader(fileStream))
{
while (transferred < length)
{
int chunkSize = Math.Min(length - transferred, BUFSIZE);
byte[] buffer = br.ReadBytes(chunkSize);
networkStream.Write(buffer, 0, chunkSize);
transferred += chunkSize;
// here you can even report some progress to adjust a ProgressBar or something
}
}
You can use Stream.CopyTo() to copy data from a source stream into another.
The CopyTo() method uses a temporary buffer as suggested by taffer.
Do not forget to Flush() the network stream afterwards.
using (Stream fileStream = File.OpenRead(tbFilename.Text))
{
TcpClient clientSocket = new TcpClient(tbServer.Text, 8080);
NetworkStream networkStream = clientSocket.GetStream();
fileStream.CopyTo(networkStream);
networkStream.Flush();
networkStream.Close();
clientSocket.Close();
}
Just trying to use Networkstream, and this is a simple code i wrote:
Client side:
TcpClient c = new TcpClient();
c.Connect("10.0.0.4", 10);
NetworkStream ns = c.GetStream();
byte[] buffer = System.Text.Encoding.UTF8.GetBytes("first");
byte[] buffer2 = System.Text.Encoding.UTF8.GetBytes("second");
MemoryStream stream = new MemoryStream();
stream.Write(buffer, 0, buffer.Length);
stream.Write(buffer2, 0, buffer2.Length);
stream.CopyTo(ns);
This is the server side:
TcpListener tl = new TcpListener(IPAddress.Any, 10);
tl.Start();
TcpClient c = tl.AcceptTcpClient();
NetworkStream ns = new NetworkStream(c.Client);
byte[] buff = new byte[5];
ns.Read(buff,0,buff.Length);
string result = System.Text.Encoding.UTF8.GetString(buff);
MessageBox.Show(result);
only when i close the entire application the MessageBox line is executed , and im always getting a blank messagebox! which mean result doesnt contain nothing...
Any help?
On the client stream is positioned at the very end of the stream. Therefore, CopyTo has nothing left to copy.
Use stream.Position = 0; before copying.
Also, you don't seem to be aware of the fact that socket reads (in fact any stream read) can return less bytes than were requested (at least one). Your reading code must account for that. TCP does not preserve message boundaries.
I am using Telnet protocol in order to read a text file from the server PC. But when I try to convert network stream to sting, it is giving some junk values. What will be the issue here?
NetworkStream ns = tcpclient.GetStream();
StreamReader streamReader = new StreamReader(ns);
StreamWriter streamWriter = new StreamWriter(ns);
byte[] bytes = new byte[tcpclient.ReceiveBufferSize];
int bytesread = tcpclient.ReceiveBufferSize;
ns.Read(bytes, 0, bytesread);
string returndata = Encoding.ASCII.GetString(bytes);
I have tried to read the text file through command prompt. Using the following steps
1. Enabled telnet server in the server pc and client in my pc.
2. change telnet port in server pc to 24
3. Using telnet command connect to server pc.
4. from telnet window> using type display the content of the text file in command prompt.
Now I want to do the same from my c# code. I have written the following code:
TcpClient tcpclient = new TcpClient();
tcpclient.Connect(<ip address>, <port>);
NetworkStream ns = tcpclient.GetStream();
StreamReader streamReader = new StreamReader(ns);
byte[] msg = Encoding.ASCII.GetBytes("type <file location>");
string returnd = Encoding.ASCII.GetString(msg);
ns.Write(msg, 0, msg.Length);
StreamWriter streamWriter = new St
byte[] bytes = new byte[tcpclient.ReceiveBufferSize];
int bytesread = tcpclient.ReceiveBufferSize;
ns.Read(bytes, 0, bytesread);reamWriter(ns);
string returndata = Encoding.ASCII.GetString(bytes);
but my code is always giving some junk output like " ÿý%ÿûÿûÿý'ÿýÿý"
ReceiveBufferSize is the size of the receive buffer, but when you read, you don't always get a full buffer. The Read method returns the actual number of bytes that were read, you should use that to limit the part of the buffer you want to decode:
byte[] bytes = new byte[tcpclient.ReceiveBufferSize];
int nRead = ns.Read(bytes, 0, tcpclient.ReceiveBufferSize);
string returndata = Encoding.ASCII.GetString(bytes, nRead);
I'm trying to make an Android app that sends a .txt file to a Windows Forms application on my computer. The problem is that not the whole file gets sent (I haven't been able to find out whether the problem is on the sending or receiving side). I only get a random part from somewhere in the middle of the .txt file to the receiving side. What am I doing wrong? The strange thing is that it has worked perfectly a few times, but now I'm never getting the beginning or the end of the file.
The Android app is written in Java, and the Windows Forms app is written in C#. filepath is the name of my file. What is the problem here?
Code for Android app (sending file)
//create new byte array with the same length as the file that is to be sent
byte[] array = new byte[(int) filepath.length()];
FileInputStream fileInputStream = new FileInputStream(filepath);
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
//use bufferedInputStream to read to end of file
bufferedInputStream.read(array, 0, array.length);
//create objects for InputStream and OutputStream
//and send the data in array to the server via socket
OutputStream outputStream = socket.getOutputStream();
outputStream.write(array, 0, array.length);
Code for Windows Forms app (receiving file)
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
byte[] message = new byte[65535];
int bytesRead;
clientStream.Read(message, 0, message.Length);
System.IO.FileStream fs = System.IO.File.Create(path + dt);
//message has been received
ASCIIEncoding encoder = new ASCIIEncoding();
System.Diagnostics.Debug.WriteLine(encoder.GetString(message, 0, bytesRead));
fs.Write(message, 0, bytesRead);
fs.Close();
Instead of reading the complete array to your memory and sending it to an outputstream afterwards, you could do read/write at the same time, and just use a "small" buffer byte array. Something like this:
public boolean copyStream(InputStream inputStream, OutputStream outputStream){
BufferedInputStream bis = new BufferedInputStream(inputStream);
BufferedOutputStream bos = new BufferedOutputStream(outputStream);
byte[] buffer = new byte[4*1024]; //Whatever buffersize you want to use.
try {
int read;
while ((read = bis.read(buffer)) != -1){
bos.write(buffer, 0, read);
}
bos.flush();
bis.close();
bos.close();
} catch (IOException e) {
//Log, retry, cancel, whatever
return false;
}
return true;
}
on the receiving side you should do the same: Write a portion of bytes as you receive them and not store them completly into the memory befor using.
This might not fix your issue, but is something you should improve anyway.
I'm creating a socket server that needs to continuously listen for incoming messages from the connected clients. Those messages will be sent in a byte[] array. I had the server working great with a StreamReader but StreamReader only works with textual represenations of the data being sent...not byte[] arrays.
Here's what I had:
StreamReader reader = new StreamReader(Client.GetStream());
string line = "";
while (true)
{
line = reader.ReadLine();
if (!string.IsNullOrEmpty(line))
{
parentForm.ApplyText(line + "\r\n");
SocketServer.SendBroadcast(line);
}
}
I need to now convert that into a raw stream somehow that will convert the stream contents into a byte[] array but I can't seem to get a handle on it.
I tried this:
while (true)
{
var bytes = default(byte[]);
using (var memstream = new MemoryStream())
{
var buffer = new byte[512];
var bytesRead = default(int);
while ((bytesRead = reader.BaseStream.Read(buffer, 0, buffer.Length)) > 0)
memstream.Write(buffer, 0, bytesRead);
bytes = memstream.ToArray();
}
//parentForm.ApplyText(bytes.Length + "\r\n");
}
but as you might guess, the while(true) loop doesn't quite work how I need it to. Can anyone help me with some code adjustment to make this work as I need it to. It needs to continuously listen for incoming messages, then when a message is received, it needs to do something with that message (the byte[] array) then go back to listening again.
TIA
I guess "listening continuously" is not task of reader its a task of listener. I ran into same problem when i was writing server using TcpListener. I am not sure what you want to do but i am posting solution for your "listening continuous" and reading into byte[] problem. I guess this code might help you:
TcpListener t = new TcpListener(IPAddress.Loopback, _port);
t.Start();
Console.WriteLine("Server is started and waiting for client\n\n");
byte[] buff = new byte[255];
NetworkStream stream;
TcpClient client;
while(true)
{
client = t.AcceptTcpClient();
if (!client.Connected)
return;
stream = client.GetStream();
while ((stream.Read(buff, 0, buff.Length)) != 0)
{
break;
}
if (0 != buff.Length)
break;
}
There's no need to convert anything. GetStream() returns a NetworkStream. See the sample Microsoft includes in the NetworkStream.Read Method. All you have to do is replace the myCompleteMessage.AppendFormat("{0}", Encoding.ASCII.GetString(myReadBuffer, 0, numberOfBytesRead)); line with an appropriate storage mechanism.