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.
Related
I use socket programming with TCPClient and NetworkStream .
My data mixed up after a while that working ever 10 seconds.
What is your idea ???
var data = Encoding.ASCII.GetBytes(request);
NetworkStream stream = client.GetStream();
stream.Write(data, 0, data.Length);
var dataRec = new byte[bufferSize];
var result = stream.Read(dataRec, 0, dataRec.Length);
var strResv = Encoding.ASCII.GetString(dataRec, 0, result);
Should I use the Async functions?
My data size per request is 100KB
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();
}
I have a few problem to send jpg data using a socket.
Sender side:
Socket client_s = new Socket(AddressFamily.InterNetwork, SocketType.Stream,ProtocolType.Tcp);
IPEndPoint serverEP = new IPEndPoint(IPAddress.Loopback, 4567);
client_s.Connect(serverEP);
NetworkStream stream = new NetworkStream(client_s);
bmp.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
Receiver side:
clientSocket = listenSocket.Accept();
NetworkStream s = new NetworkStream(clientSocket);
Bitmap slice_bmp = new Bitmap(s);
Graphics g = this.CreateGraphics();
g.DrawImage(slice_bmp,0,0);
When I execute the above, Bitmap slice_bmp = new Bitmap(s); is blocked until closing sender's socket. After sender's socket is closed, an image is drawn normally. I want to know why that operation is blocked?
Also, is it right using instance of Networkstream as argument of constructor of Bitmap? (My code is based on inheritance)
First of all, I would suggest you to use Flush() method of the NetworkStream to be sure that all the data has been sent.
Socket client_s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint serverEP = new IPEndPoint(IPAddress.Loopback, 4567);
client_s.Connect(serverEP);
NetworkStream stream = new NetworkStream(client_s);
bmp.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
stream.Flush(); //flush everything
On the receiver's side, you should first read all the bytes of the image into a byte array. From that byte array you could construct the MemoryStream and than Bitmap from that stream.
clientSocket = listenSocket.Accept();
NetworkStream s = new NetworkStream(clientSocket);
int bytesRead = 0;
int howMany = 0;
byte [] byteBuffer = new byte[100000];
do
{
howMany = s.Read(byteBuffer, bytesRead, 10000);
bytesRead += howMany;
if(bytesRead>=byteBuffer.Length)
byteBuffer = ResizeByteArray(byteBuffer);
}
while (howMany > 0 && s.DataAvailable);
MemoryStream ms = new MemoryStream(byteBuffer);
Bitmap slice_bmp = new Bitmap(ms);
Graphics g = this.CreateGraphics();
g.DrawImage(slice_bmp, 0, 0);
g.Dispose();
If the image is larger from the capacity of the instantiated byte array, then you need to resize it. You could use this helper method:
private byte[] ResizeByteArray(byte[] arr)
{
byte[] newArr = new byte[arr.Length * 2];
Array.Copy(arr, newArr, arr.Length);
return newArr;
}
And as a side note, always call Dispose on Graphics object that you create manually (like in this case). I checked the code and it works.
It appears you are working on a single threaded-application, or at least on the UI-thread of a multi-threaded-application. The blocking appears because your bitmap object is waiting for its construction to be complete. And as it takes a while to read from a stream over a network, your program will not continue until your bitmap-object is fully created.
If you wanted your program to go on, you would need to create a thread and have it read from the stream and create the bitmap. When the bitmap is ready you could fire an event and act appropriately.
As NetworkStream is a subclass of System.IO.Stream it is perfectly fine! You can use any System.IO.Stream to create an object that requires a stream. The only result is, as you experienced, it might take a little longer than creating the image, e.g. from a System.IO.FileStream.
Have a look at MSDN most of the stuff is well described.
This is because bitmap class waits for transmission to end:
First receive byte data buffer separately,
then create memory stream from it and then create bitmap.
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.
The code below reads everything there is to read from tcp client stream, and on the next iteration it will just sit there on the Read() (i'm assuming waiting for data). How can I ensure it doesn't and just returns when there's nothing there to read? Do I have to set low timeout, and respond to an exception when it fails out? Or there's a better way?
TcpClient tcpclnt = new TcpClient();
tcpclnt.Connect(ip, port);
Stream stm = tcpclnt.GetStream();
stm.Write(cmdBuffer, 0, cmdBuffer.Length);
byte[] response = new Byte[2048];
MemoryStream ms = new MemoryStream();
byte[] buffer = new Byte[2048];
int length;
while ((length = stm.Read(buffer, 0, buffer.Length)) > 0)
ms.Write(buffer, 0, length);
byte[] response = ms.ToArray();
tcpclnt.Close();
TcpClient has two properties that I would play with.
NoDelay Gets or sets a value that disables a delay when send or receive buffers are not full.
ReceiveTimeout Gets or sets the amount of time a TcpClient will wait to receive data once a read operation is initiated
Maybe you should use multithreading. One thread should wait for data, another should process received data.
Does the server have "Keep Connections Alive" on ?
I have had servers which will send you a stream of empty bytes as long as you request them.
Turning "Keep Connections Alive" stopped it doing this.
var socket = new System.Net.Sockets.TcpClient();
socket.NoDelay = true;
socket.Connect(uri.Host, port);
var ns = socket.GetStream();
int timeout = 500; //ms
DateTime lastReceived = DateTime.Now;
string buffer = "";
while (true)
{
if (ns.DataAvailable)
{
var b = ns.ReadByte();
buffer += b + ", "; //customise this line yourself
lastReceived = DateTime.Now;
continue;
}
if (lastReceived.AddMilliseconds(timeout) < DateTime.Now) break;
System.Threading.Thread.Sleep(timeout / 5);
}