COM port communication with Virtual PC (part 2) - c#

This question is related to my earlier question.
Connecting to the pipe is now successful, but I still cannot read (or write) any data from the port.
My first guess was, that the data are buffered. But even when I write (on the client site) 5000 bytes (the buffer in NamedPipeClientStream is 512 byte large), I do not receive any
data.
PipeOptions.WriteThrough didn't changed anything, too.
When I do not use a pipe, but a textfile (in the Virtual-PC settings) to redirect the data written to the COM-Port, the data are written as expected to the textfile. So the client test programm, running in Virtual-PC, is doing fine. The problem is likely in my code below.
var pipe = new NamedPipeClientStream(".", "mypipe", PipeDirection.InOut, PipeOptions.WriteThrough);
pipe.Connect();
// this is blocking
int i = pipe.ReadByte();
var reader = new StreamReader(pipe);
// this is blocking, too
var s = reader.ReadLine();
Update:
The code I am running on the guest os:
var port = new SerialPort("COM1");
port.Open();
port.WriteLine("Hallo");
Using 'echo' in an command prompt as telewin suggested works fine.
What is the difference between echoing and using the above code?

Sorry for the late reply, hope it's still relevant...
In my tests, "echo hello > com1" only works before you run your program (which initiates a new SerialPort) inside VPC. After you run it, "echo hello > com1" will no longer be seen by the host program, until the guest is rebooted.
This suggests that the initialization of the SerialPort itself does something permanent. Using Reflector we find that SerialPort's ctor does nothing of consequence, but its Open method calls the ctor for SerialStream. This ctor does quite a bit: it sets read/write buffers, Rts/Dtr, and handshake mode. After some trials, it seems that the Rts/Dtr screw up the "echo hello > com1". Can you please try this modified code inside VPC:
var port = new SerialPort("com1");
port.DtrEnable = true;
port.RtsEnable = true;
port.Open();
port.WriteLine("Hallo");

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.

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

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)
{
;
}
}

C# <-> Java socket communication

I am making a .NET application which is supposed to communicate with a Java application over the sockets.
Here is the .NET code:
string str = " MSG1234";
TcpClient client = new TcpClient();
client.Connect("127.0.0.1", 8080);
byte[] msg = Encoding.UTF8.GetBytes(str);
client.Client.Send(msg);
StreamWriter sw = new StreamWriter(client.GetStream());
StreamReader sr = new StreamReader(client.GetStream());
while (true)
{
Console.WriteLine(sr.Read());
}
The problem is that the Java application wouldn't send the answer. The application is a 3rd party piece of software and I can't change it, however I have downloaded a decompiler and found the relevant piece of code in the Java class:
try {
while (this.is.available() <= 0);
body = new byte[this.is.available()];
this.is.readFully(body);
System.out.println("Message received");
} catch (Exception e) {
System.out.println("Error: " + body);
}
"is" in this case is a DataInputStream. Here is what happens:
1. I create a socket and send the message
2. I wait for response, nothing happens
3. I close the app manually - it causes the socket to expire
4. Suddenly the whole message appears in the Java application's log. That means the exception happened and there actually is something in the body.
Can you perhaps point me out where the error could be? I believe the this.is.readFully(body) line shouldn't be there, but I'm not sure. Perhaps I should send an EOF from the C# code manually, but I wasn't able to find out how.
Another, minor problem with that code is, that the first two characters of the message are stripped away, that's why I have included the two space in front of the actual message.
Thank you in advance.
EDIT
So I have tried to fill the socket with some random data and I've finally got the answer:
for (int i = 0; i < 600; i++)
{
sw.Write("some long random string");
sw.Flush();
}
This not a good solution though, because the message I send has to be exact.
Then I have tried to close the socket after relevant data has been sent by soc.Disconnect(false); which causes the Java application's log to fill with proper debug information.
Is there any way to send EOL to the socket so the Java app would stop listening and would start sending the data?
Thank you.
EDIT 2
I have tried to create a Java client to connect to the server, the same thing has happened.
Then I have created a dummy server to listen on the same port as the Java app I'm connecting too, it has also behaved the way as the Java app should and it was working.
Now I feel that my only chance is to send EOT or EOF command to the stream, but I have no idea how to do it on .NET and I wasn't able to find the answer on the internet either.
If the Java application is from a third party, chances are that you're doing something wrong. The DataInputStream.readFully(byte[]) function block the application until it has read the number of bytes that the byte array can hold, so the snippet of code you have is from the read operation.
I also see that you use the Socket.Send(byte[]) function to communicate with the Java application, I recommend you to use something higher level like StreamWriter or BinaryWriter, more less like this:
StreamWriter = new BinaryWriter(client.GetStream());
StreamWriter.Write(msg);
StreamWriter.Flush();
Can you try to flush both the StreamWriter (so it writes its buffer to the stream object) and the actual NetworkStream you got from client.GetStream() (so it sends a packet, despite the packet not being "full" yet)?
NetworkStream ns = client.GetStream();
StreamWriter sw = new StreamWriter(ns);
StreamReader sr = new StreamReader(ns);
// ...
sw.Flush();
ns.Flush();
Most likely, you are not flushing all that you need to flush. Have you tried looking at the network communication with e.g. wireshark - is the data actually going out? If not, the problem is in your .NET code.

c# .net Windows 8 App TcpClient code port to StreamSocket

I had this code prior to .net 4.5
_Connection = new TcpClient(hostname, port);
_Stream = _Connection.GetStream();
For Windows 8 App I changed to:
_Connection = new StreamSocket();
await _Connection.ConnectAsync(new HostName(hostname), port.ToString());
_DataReader = _Connection.InputStream.AsStreamForRead();
_DataWriter = _Connection.OutputStream.AsStreamForWrite();
I thought this to be the simplest solution as I don't have to change any underlying code anywhere else, as I am still using Stream to read/write data.
This code does not work as expected though, I manage to write stuff successfully on the stream, but when it's time to read the stream, I keep getting '\n' - which is far off from my expected response.
Found a solution to this. Hope someone finds it useful.
All i needed to do was flush the stream in _DataWriter (this needs to be done everytime something is written to the stream) and then the _DataReader stream started working as expected.

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