Reading data from a StreamSocket - c#

From looking at the example application on the Microsoft Website How to connect with a stream socket (XAML)
, I have learned how to connect to a server, and send string to the server. However, the example doesn't quite extend on reading data from the socket.
The server is a c# windows console application and what it does is send data to the mobile client by using a network stream.
//send user response
//message is a frame packet containing information
message = new Message();
//type 1 just means it's successfull
message.type = 1;
//using Newton JSON i convert the Message Object into a string object
string sendData = JsonConvert.SerializeObject(message);
//conver the string into a bytearray and store in the variable data (type byte array)
byte[] data = GetBytes(sendData);
//netStream is my NetworkStream i want to write the byte array called data, starting to from 0, and ending at the last point in array
netStream.Write(data, 0, data.Length);
//flushing the stream, not sure why, flushing means to push data
netStream.Flush();
//debugging
Console.WriteLine("sent");
In order to read data from a stream, the DataReader class is used. I am quite new to c# Mobile, and the documentation on the DataReader class doesn't provide any implementations of examples, so how can I read data from the Stream Socket?
Using the example code from microsoft;
DataReader reader = new DataReader(clientSocket.InputStream);
// Set inputstream options so that we don't have to know the data size
reader.InputStreamOptions = InputStreamOptions.Partial;
await reader.LoadAsync(reader.UnconsumedBufferLength);
But now I am not sure how to read the byte array sent from the server.

Related

Why is using StreamWriter.WriteLine, followed by StreamWriter.BaseStream.WriteByte unreliable?

I am developing a networking application.
For sending and receiving data, I am using NetworkStream that I get from TcpClient.
For sending text, I wrapped NetworkStream in a StreamWriter, and I simply call StreamWriter.WriteLine(text), followed by StreamWriter.Flush().
For sending 1 byte flags from server to client (that are required for in my own communication protocol), I am using StreamWriter.BaseStream.WriteByte(byte). So, it is all the same underlying stream and it worked great until I got into this situation. The following code is where it breaks:
// This is server sending data to client.
writer.WriteLine(text);
writer.Flush();
writer.BaseStream.WriteByte(flag);
// This is client trying to read incoming data from server.
string text = reader.ReadLine(); // This will read text successfully.
int flag = reader.BaseStream.ReadByte(); // Problem is here: It will block here as if there is no data.
However, if I put some delay between flushing data and sending the byte, everything works fine...
// This is server sending data to client.
writer.WriteLine(text);
writer.Flush();
Thread.Sleep(1000); <-------------------------------- delay
writer.BaseStream.WriteByte(flag);
// This is client trying to read incoming data from server.
string text = reader.ReadLine(); // This will read text successfully.
int flag = reader.BaseStream.ReadByte(); // Now the byte is read successfully as well.
Can someone please explain why this is happening and how I can fix it?

Send data to remote server using Sockets

I want send data to remote server i know its IP address and Port number. Let say it is xxx.xxx.xx.xx and port number is 123. It works with TCP. I want to send first-last name, email, and host name where host name is the new name which i am going to give my machine. Server should give me response in the form of key value as 123-01234. Here I do not understand how i would send data to server using socket. I did work with just simple strings. I have one last more question, Have i need to make server program in it.
public void Connect(String server)
{
Int32 port = 123;
TcpClient client = new TcpClient(server, port);
string FNAME = "reet";
Byte[] data = System.Text.Encoding.ASCII.GetBytes(FNAME);
NetworkStream stream = client.GetStream();
stream.Write(data, 0, data.Length);
Console.WriteLine("Sent: {0}", FNAME);
data = new Byte[256];
String responseData = String.Empty;
Int32 bytes = stream.Read(data, 0, data.Length);
responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
Console.WriteLine("Received: {0}", responseData);
stream.Close();
client.Close();
}
To open a socket, you can either use the Socket type, or the TcpClient type (assuming it is TCP). The IP address and port are specified in the constructor for either. Then you need to decide whether you're going to use the Socket API, vs the NetworkStream API, to actually do the communications. If you're using a raw Socket (.Client on a TcpClient), then you use the Send and Receive methods (and the related async options). If you prefer a Stream, then that is .GetStream() on TcpClient, or new NetworkStream(socketInstance) for Socket, and Read / Write. With a Stream, you can of course wrap it in a StreamReader / StreamWriter if you want a simple text API, but it isn't clear whether your socket API is text or binary. You mention wanting to receive 123-01234, but that could be encoded many different ways, so ultimately you need to be very clear about what the socket API expects, at the byte level.

C# Tcplistener server

I have a TCPListener (server side).
When the data is retrieved, it has all the streams concatenated into one string. I need to use them separately. I read somewhere on the internet that I need to send the length of each stream and handle it on the server side. I did so, but when I retrieve the stream, the length is not numeric, rather it has the values "0?".
I am using the following code to retrieve the streams:
bytes = new byte[listener.ReceiveBufferSize + 1];
int bytesRec = handler.Receive(bytes);
data += Encoding.ASCII.GetString(bytes, 0, bytesRec);
This code will get me all the streams concatenated into the "data" field. So I need to be able to retrieve each stream separately. Any thoughts?

HttpWebResponse Stream reading in uneven chunks

I am using the stream from HttpWebRequest.GetResponse().GetResponseStream() to read data from a streaming web API. I use Begin/EndRead on the stream with a buffer of 65K bytes. I can see that data is being returned in the following pattern:
16383 bytes read.
1 bytes read.
16383 bytes read.
1 bytes read.
16383 bytes read.
1 bytes read.
etc...
Obviously the 1 byte reads introduce a lot of inefficiency in the process, and the buffer size I provide is large enough to fit 16384 bytes or more. Is there anything I can do as a client to improve this or is simply up to the server how it's streaming data to me?
The reader code is basically:
var buffer = new byte[65536];
using (var stream = response.GetResponseStream()) {
while (true) {
var bytesRead = await AsyncRead(stream.BeginRead, stream.EndRead, buffer);
Console.WriteLine($"{bytesRead} bytes read.");
// do something with the bytes
}
}
where AsyncRead just calls BeginRead(buffer, 0, buffer.Length, callback, null), then EndRead in the callback and returns the return value of EndRead.
BTW this is on .NET 4.0, no HttpClient.
What exactly are you trying to achieve by sending the HTTPWebRequest to the target server?
Are you trying to read a live response from the server after asking the server for data or initializing a request between your client application and the target server? If you are try to send an HTTPWepRequest and an HTTPWebResponse to the target server then convert the response given from the server to a stream then use System.IO.StreamReader to read the in-coming stream!
Then just to be on the safe side convert the stream that was read by the System.IO.StreamReader method into UTF-8 if that is your overall goal!
After converting to UTF-8 you can now print the output stream into a string value which you can output to console or wherever you want to send the output string!
I hope this is what you wanted if not then I have been essentially useless! :P

Sending a image file using a socket in C# (Large Data)

i want to send a large data (image) approx . 1MB file though a socket connection
Question 1
following code snippet of the socket client which i currently use to send a a text message .. how i can modify this to send a file ?
NetworkStream serverStream = clientSocket.GetStream();
byte[] outStream = System.Text.Encoding.ASCII.GetBytes(richTextBox1.Text+"$");
serverStream.Write(outStream, 0, outStream.Length);
serverStream.Flush();
Question 2 : What modifications that required in both socket client and server to send and get large files ?
For large data portions you will probably need some kind of transmitting by portions. In your snippet you get all of the data in the array which couldn't be possible if file is large enough (or at least not suitable if it is not just one file to send).
Sending side will be something like that:
const int bufsize = 8192;
var buffer = new byte[bufsize];
NetworkStream ns = socket.GetStream();
using (var s = File.OpenRead("path"))
{
int actuallyRead;
while ((actuallyRead = s.Read(buffer, 0, bufsize)) > 0)
{
ns.Write(buffer, 0, actuallyRead);
}
}
ns.Flush();
Receiving site is just symmetric.
A socket doesn't care if you send text or binary data. Or how much you send. If there's any trouble then it is at the receiving end, code you didn't post. A classic mistake is to forget that a NetworkStream is a stream and not a sequence of packets. The Read() call at the receiving end can return any number of bytes. It won't be the number of bytes you wrote in the Write() call, depending on how routers in between the two machines broke up the IP packets and how much data is buffered in the receiver. You are probably getting away with calling Read only once because the string is short. That is definitely not going to work when you send a lot of data.
You need a protocol to help the receiver figure out when it received all the data. A simple way to do this is by first sending the length of the data. The receiver can then first read that length, then know how long to keep calling Read() to get the rest of the data.
You can arbitrarily extend this protocol by, say, sending the name of the file. Etcetera. Although that by the time you're done, you'd be close to having re-invented FTP.
If all you want to do is to send an image and you don't need any metadata, you can use code like this:
Server:
var listener = new TcpListener(address, port);
listener.Start();
using (var incoming = listener.AcceptTcpClient())
using (var networkStream = incoming.GetStream())
using (var fileStream = File.OpenWrite(imagePath))
{
networkStream.CopyTo(fileStream);
}
listener.Stop();
Client:
var client = new TcpClient();
client.Connect(address, port);
using (var networkStream = client.GetStream())
using (var fileStream = File.OpenRead(imagePath))
{
fileStream.CopyTo(networkStream);
}
client.Close();
If you want to compress the file, you can use GZipStream.
This code uses CopyTo() method, which is available in .Net 4, but you can write it yourself in earlier versions.

Categories