StreamSocket : datareader.LoadAsync waits infinte even when data is avaialbe - c#

I have the following code in my Windows phone 8 app.
//connection code, done during app start
socket = new StreamSocket();
await socket.ConnectAsync(serverHostName, serviceName);
dataReader = new DataReader(socket.InputStream);
dataReader.InputStreamOptions = InputStreamOptions.Partial;
dataWriter = new DataWriter(socket.OutputStream);
After the connection is established, I have another thread which checks for incoming network packets
await dataReader.LoadAsync(2048);
dataReader.ReadBytes(buffer);
----------
Workflow is as follows
Phone connects to server using socket.ConnectAsync
Server responds with initial message (Phone receives this properly in dataReader.LoadAsync function)
Phone now sends the 'business specific' request
Server now replies with 'business specific' response (Problem lies here. Phone doesn't receive the reply from server at some of the times).
There is no scenario difference between working state' and 'non working state'.
So I tried to debug this. I put a breakpoint for dataReader.LoadAsync and saw that execution waits infinitely at the call.
To make sure that the server is sending data properly, I ran the app in Windows phone emulator and ran the WireShark network analyzer in the PC. I could see that packets are being received for the IP Address of the phone.
Anyone has any hints on why the dataReader.LoadAsync function call doesn't return at all, when there is data ready to be read in the socket?

I faced the same problem. It is especially bad for Bluetooth RFCOMM SPP serial port devices, because the underlying Rfcomm-object does not provide capabilities for setting ReadTimeout values.
Edit: The InputStreamOptions.Partial option seems to be working UWP Win10 platform, but it is only useful when you are already know much data you are expecting. Otherwise it will wait indefinitely on the last call.
I almost gave up, when I found in references below these lines to solve the problem by using a CancellationTokenSource
//connect your Windows.Devices.Bluetooth.Rfcomm.RfcommDeviceService
// see the Bluetooth chat example
[...]
StreamSocket streamSocket = new StreamSocket();
await streamSocket.ConnectAsync(...); //connect to Bluetooth device
DataReader dataReader = new DataReader(inputStream); // to read from the stream
try
{
var timeoutSource = new CancellationTokenSource(1000); // 1000 ms
uint numberBytesToRead = 256;
var data = await dataReader.LoadAsync(numberBytesToRead).AsTask(timeoutSource.Token);
}
catch (TaskCanceledException)
{
// we will get here, and everything looks fine, but the problem is:
// The underlying streamSocket is also closed!
// we can not re-use the streamSocket. Any more calls to LoadAsync results in exceptions (something about the object being not assigned...)
// we need to do a full await streamSocket.ConnectAsync(...) again, but that takes ~3 seconds.
}
So this method is only a brute-force, last-resort attempt at a time-out.
The method from #mayu works very good (serialDevice.ReadTimeout), but only on devices of class Windows.Devices.SerialCommunication.Serial​Device, but not on
Windows.Devices.Bluetooth.Rfcomm.RfcommDeviceService. I don't know how the situation is for TCP/IP sockets.
In short, is there any usable time-out for RFCOMM SPP Bluetooth connections?
Or any method to know ahead of time if .LoadAsync(1) will block, because no new data is available?
This fellow over at MSDN has the exact same problem, but MS don't know an answer either: https://social.msdn.microsoft.com/Forums/vstudio/en-US/71ea17d4-ca16-43c2-ab43-02d5301def3f/chow-to-set-timeout-on-streamsocketreadasync?forum=wpdevelop
References:
In UWP StreamSocket, can I read data with timeout and leave the connection open if timeout elapses
https://social.msdn.microsoft.com/Forums/en-US/8a5c4fdc-28d6-4a22-8df6-bc519efeaa4d/how-to-control-the-timeout-for-reading-from-streamsocket?forum=winappswithcsharp
DataReader of SocketStream for UWP App

"According to documentation when using InputStreamOptions.Partial, you should use UnconsummedBufferLength instead of an hardcoded value"
That sample seems to be broken.
"await reader.LoadAsync(reader.UnconsumedBufferLength);" is equivalent to
await reader.LoadAsync(0); and then it's not possible to read any data, since you have no buffer to read from.
I'm testing this now and it seems like "reader.InputStreamOptions = Partial;" has no effect at all. My only workaround is to lower the read timeout.

According to documentation when using InputStreamOptions.Partial, you should use UnconsummedBufferLength instead of an hardcoded value :
DataReader reader = new DataReader(clientSocket.InputStream);
// Set inputstream options so that we don't have to know the data size
reader.InputStreamOptions = Partial;
await reader.LoadAsync(reader.UnconsumedBufferLength);
Sample is there

I had a similar problem using Windows Remote Arduino library and SerialUSB stream. I had to change this library and call LoadAsync(1) instead of original LoadAsync(100). Now the code is working fine.
see: https://github.com/ms-iot/remote-wiring/issues/111

For serial devices you need to set
device.ReadTimeout = TimeSpan.FromMilliseconds(100);
for the LoadAsync to return before the buffer is full.

The only way I found to get round not knowing the size of the data before reading was to read one byte at a time until I got a timeout. Feels horrid, but works. Is there a better way yet?
private async Task ReadData(CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
DataReaderObject.InputStreamOptions = InputStreamOptions.Partial;
uint data = 0;
uint bufferLength = DataReaderObject.UnconsumedBufferLength;
var timeoutSource = new CancellationTokenSource(100); // 100 ms
try
{
while (true)
{
data = await DataReaderObject.LoadAsync(1).AsTask(timeoutSource.Token);
if (data > 0)
{
String temp = DataReaderObject.ReadString(data);
TemperatureValue.Text += temp.Trim();
}
}
}
catch (Exception)
{
;
}
}

Related

Replicate PuTTY's raw connection with sockets

I am working with a heat cell with which i can only communicate through Ethernet. When trying to connect to it using sockets, I am stuck on waiting for the Receive() method to end.
I've checked the connection using PuTTY in raw mode and it worked just fine, I was able to send and receive messages.
This led me to believe that I needed to use some kind of raw communication as well, hence why I tried to use SharpPCap and the like. Using this, I am able to read from the cell (although I am faced with a few issues that aren't related to this post).
However, since I'm not very experienced with networking, I was wondering if there was a way to obtain the same results as when I used PuTTY's raw mode but using only Sockets ?
I've come accross this question that was left unanswered, apart from the fact that the author was advised not to use SocketType.Raw.
Below is the example from MSDN documentation that I adapted for my tests. It is supposed to send a request and then listen for the answer.
static void Main(string[] args)
{
System.Net.IPAddress host = System.Net.IPAddress.Parse("10.0.0.3");
int port = 2049;
Socket socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
socket.Connect(host, port);
if (socket.Connected)
{
string request = "99997¶1¶1\\r";
var byteSent = Encoding.Default.GetBytes(request);
var byteReceived = new byte[256];
socket.Send(byteSent, byteSent.Length, 0);
int bytes = 0;
do
{
bytes = socket.Receive(byteReceived, byteReceived.Length, 0); // this is the line I'm being stuck on
} while (bytes > 0);
Console.WriteLine($"Result : {Encoding.Default.GetString(byteReceived)}");
Console.ReadLine();
}
else
{
Console.WriteLine("Connection Failed");
Console.ReadLine();
}
}
UPDATE
I used WireShark to take a look at what was being sent from my application. Turns out the 'CR' and 'LF' werent sent correctly. But correcting this didn't solve my problem.
I can see the server's answer to my request on WireShark, but still I can't read anything using socket.Receive(). Could it be possible that the server is faster to answer than my machine is to start listening ? I tried setting up the socket.ReceiveTimeout property and put my send/receive instructions in a loop, but still nothing returning from the Receive() statement.
The socket is in blocking mode by default (cf Socket.Blocking). That mean that, for your case, blocking until 256 byte has been read (Without timeout by default Socket.ReceiveTimeout).
You may want to set the Blocking mode to false, or set a Receive timeout in order to not block indefinitly.
Alternatively, you may want also to use async method to avoid blocking the main thread.

System.Net.WebSockets Connection OPEN before server is listening

I'm running into issues on a setup that's under load accepting the connection and setting it to OPEN before the server is read to read from the socket.
Example(not the actual code):
while (true) {
var objContext = HttpListenerContext.GetContext();
if (objContext.Request.IsWebSocketRequest){
var WebSocket = (await HttpListenerContext.AcceptWebSocketAsync(null)).WebSocket;
while (WebSocket.State == WebSocketState.Open) {
var buffer = new byte[BUFFERSIZE];
var result = await WebSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken);
....
}
}
}
When adding breakpoints on the client and server I've noticed after the AcceptWebSocketAsync is called, the clients receives that the connection is 'OPEN' and ready to be used and starts sending data.
The issue is that ReceiveAsync hasn't started at that time yet, reason is that the ReceiveAsync is a bit slower to start running the task, they stay in WaitingForActivation a bit longer then on an idle system due to the server in question being under high load (lots of other tasks/threads and low number of cpu's).
Is this normal behavior and how can this be stopped?
Had someone go over my code, that person found that the ReceiveAsync being called later isn't an issue, the info is in the buffer.
It was higher up that an event handler was attached too late.

Streamreader.ReadAsync() stops reading data from persistent network stream

I am attempting to read the output of an IP phone system. My current implementation is using Streamreader.ReadAsync() to read a single char at a time from the stream into a result string, and then when I hit the custom line terminator provided by the phone system I am parsing the result string and storing the data. Here is a sample:
using (var monitor = new TcpClient(ip, port))
{
try
{
using (var reader = new StreamReader(monitor.GetStream()))
{
var streamChar = new char[1];
while (true)
{
await reader.ReadAsync(streamChar, 0, streamChar.Length);
What I am finding is that this implementation works properly during the day, but soon after 5PM I stop logging data. I am spitting out the read content to a file and I see no difference in the raw data provided at the time that logging ceases. When the ReadAsync() method hangs, I still see an open socket using netstat. I tested tonight and confirmed that if I simply allow the app to create a new TcpClient connecting to the same source within the same instance of the logging application, it begins receiving data normally.
I have previously tried using reader.EndOfStream and reader.Peek() to determine when to read the next char, but switched to this implementation because my understanding is that EndOfStream and Peek are blocking operations. I had seen the app hang at these conditionals, so I got rid of them and replaced them with what you see based on the understanding that this IP phone system will perpetually send data when new calls are received.
I am reaching out to see if anyone can confirm whether my implementation is flawed or whether I need to start focusing more on the phone system itself. Thank you for your help.
I decided to compensate for the timeout by writing back a single byte to the endpoint at a periodic interval. This resolved the issue and the connection is now remaining open. I had to deal with the response provided by the endpoint, but it would only reply with old call data that I simply discard.

How can I read from a socket repeatedly?

To start I am coding in C#. I am writing data of varying sizes to a device through a socket. After writing the data I want to read from the socket because the device will write back an error code/completion message once it has finished processing all of the data. Currently I have something like this:
byte[] resultErrorCode = new byte[1];
resultErrorCode[0] = 255;
while (resultErrorCode[0] == 255)
{
try
{
ReadFromSocket(ref resultErrorCode);
}
catch (Exception)
{
}
}
Console.WriteLine(ErrorList[resultErrorCode[0] - 48]);
I use ReadFromSocket in other places, so I know that it is working correctly. What ends up happening is that the port I am connecting from (on my machine) changes to random ports. I think that this causes the firmware on the other side to have a bad connection. So when I write data on the other side, it tries to write data to the original port that I connected through, but after trying to read several times, the connection port changes on my side.
How can I read from the socket continuously until I receive a completion command? If I know that something is wrong with the loop because for my smallest test file it takes 1 min and 13 seconds pretty consistently. I have tested the code by removing the loop and putting the code to sleep for 1 min and 15 seconds. When it resumes, it successfully reads the completion command that I am expecting. Does anyone have any advice?
What you should have is a separate thread which will act like a driver of your external hardware. This thread will receive all data, parse it and transmit the appropriate messages to the rest of your application. This portion of code will give you an idea of how receive and parse data from your hardware.
public void ContinuousReceive(){
byte[] buffer = new byte[1024];
bool terminationCodeReceived = false;
while(!terminationCodeReceived){
try{
if(server.Receive(buffer)>0){
// We got something
// Parse the received data and check if the termination code
// is received or not
}
}catch (SocketException e){
Console.WriteLine("Oops! Something bad happened:" + e.Message);
}
}
}
Notes:
If you want to open a specific port on your machine (some external hardware are configured to talk to a predefined port) then you should specify that when you create your socket
Never close your socket until you want to stop your application or the external hardware API requires that. Keeping your socket open will resolve the random port change
using Thread.Sleep when dealing with external hardware is not a good idea. When possible, you should either use events (in case of RS232 connections) or blocking calls on separate threads as it is the case in the code above.

Unable To Accept TcpClient a Second Time C#

I am new to both C# and to client-server programming. Right now, for class, I'm attempting to create an FTP client without using any pre-established FTP libraries. I feel like I have the project down for the most part, however I'm running into a problem when I make more than one call that requires use of the data port (list, retr, etc.) Here is a sample of the code that is breaking:
writer.WriteLine(portcmd);
writer.Flush();
GetServerMessage(stream);
writer.WriteLine("list ");
writer.Flush();
tmpserver = new TcpListener(IPAddress.Any, 3128);
tmpserver.Start();
tmpclient = tmpserver.AcceptTcpClient();
Console.WriteLine("gothere");
if (!tmpclient.Connected)
{
tmpserver.Start();
}
StreamReader tmpreader = new StreamReader(tmpclient.GetStream());
GetServerMessage(stream);
while (tmpreader.Peek() != -1)
{
Console.WriteLine(tmpreader.ReadLine());
}
tmpclient.Close();
tmpserver.Stop();
GetServerMessage(stream);
Getservermessage is a method that takes a network stream and prints out everything available within a .5 second timeout, stream is the NetworkStream for the current connection to the FTP server, and writer is that same network stream wrapped in a StreamReader for ease of writing ASCII characters to the server. In case you are wondering why I use a stream reader to read from the data connection, it is because the server closes the connection after it transmits the data so I could easily get an eof notification. My GetServerMessage method was for some reason breaking when I used the closed network stream.
This code is sending the port command to the FTP server to inform it that I will be requiring a data connection (first 2 lines) Then sending the list command, establishing the data connection to the server, getting the desired information, and then terminating the data connection (the rest of the code).
This code will execute without flaw the first time I run it but if I try it again, it hangs on the 'tmpclient = tmpserver.AcceptTcpClient();' line. It never reaches the "gothere" print statement. I believe this is because I am receiving the client from the same machine on the same port but I'm not sure. I tried adding a Boolean value to make sure the AcceptTcpClient() only ran once but then I got a runtime error and visual studio informed me that I may have 'released resources before I was done with them' I predicted this would be a problem but how can I tell if the server reestablishes the connection after it has closed it once?
At the end of the given code I stop tmpserver and close tmpclient. I originally did this because I knew the FTP server would close the connection when it was finished transmitting and thought it was the proper thing to do. I find if I comment out these lines, the code will execute more than once but the streams appear to be empty... I'm not sure if this information is helpful but I figured I'd mention it.
I apologize if I am unclear at all but my lack of knowledge with the subject makes it difficult to articulate my problem. If there is any confusion over what the problem is I'd be happy to attempt to clear it up.
To be able to accept another client you should execute tmpclient = tmpserver.AcceptTcpClient(); and waiting for the first client to finish its works(before accepting second client) may not be a good idea
Here is a sample server code that waits for the connections and echoes strings sent from each client. You can test it with telnet localhost 3128
Thread t = new Thread(Server);
t.IsBackground = true;
t.Start();
-
void Server()
{
TcpListener listener = new TcpListener(IPAddress.Any, 3128);
listener.Start();
while (true)
{
var client = listener.AcceptTcpClient();
new Thread(() =>
{
using (client)
{
var reader = new StreamReader(client.GetStream());
var writer = new StreamWriter(client.GetStream());
while (true)
{
string line = reader.ReadLine();
if (line == "QUIT") break;
writer.WriteLine("From Thread[" + Thread.CurrentThread.ManagedThreadId + "] > " + line);
writer.Flush();
}
}
}).Start();
}
}
OK, it's like this. To do a server in a simple manner, you need to thread off the code that handles the client socket. When the accept returns, create and start a thread, passing it the 'tmpclient' and then loop around to the accept call again so that any new client can connnct up. In the newly-spawned server<> client thread, read and write to the passed socket in a loop to communicate with the client.
Once you close your tcp client stream, you can no longer read from the stream you pulled from it.
var stream = tcpClient.GetStream();
...
tcpclient.Close();
...
stream.Read .. fail
The client would have to request another connection,
OR
You should keep your tcp client sockets open.
More complex servers will keep some metadata (state) cached about the client so when sockets unexpectedly close - and the client quickly tries to reconnect, the server can continue processing the smoothly.

Categories

Resources