Serial Port Request-Response communication using c# - c#

I want to do serial port communication with a machine which uses RS232-USB ports.
I am using serial port class. I am very new to the concept. In my first Machine interfacing I only had to do the serialport.readLine( to get the readings from the machine and there was no need to send ACK /NAK). but for the new machine interface the document says following things:
The following is an example of the RA500 communication:
Computer :<05h 31h 0dh>
RA500 :1st line of information
Computer :<06h 0dh>
RA500 :2nd line of information
Computer :<06h 0dh>
RA500 :”EOF”<0dh>
What i understood from this is i have to write to comport before reading from it. this is what i am doing in my code:
ACK = "06 0d"; NAK = "15 0d"; str = "05 31 0d";
while (count <= 5)
{
rx = ComPortDataReceived(str);
if (!string.IsNullOrEmpty(rx))
{
str = ACK;
returnReading += rx;
}
else if (string.IsNullOrEmpty(rx)) str = NAK;
count++;
}
private string ComPortDataReceived(string str)
{
string Rx = string.Empty;
string exceptionMessage = string.Empty;
try
{
byte[] bytes = str.Split(' ').Select(s => Convert.ToByte(s, 16)).ToArray();
comPort.Write(bytes, 0, bytes.Length);
Rx = comPort.ReadExisting();
PEHRsLibrary.writeTextFile(DateTime.Now + " RxString :" + Rx);
return Rx;
}
catch(Exception e){}
when i use this code i am receiving empty strings as responce. but if i use comPort.ReadExisting() only without using comPort.Write i am receving a string with all the readings but the probblem is it only gives one line of information and dosnt give 2nd or 3rd line readings.
when i try using comPort.ReadLine() after Write() I am getting Timeout exception.
i dont know what i am doing wrong in this case. I am writing ACk after receving 1st line but not receving 2nd line. Next thing i am gonna try is read() as byte and then convert it to string instead of using ReadExisting(). Any other way i can do this?

Related

Named Pipes IPC: Python server, C# Client

Title sums it up. There are plenty of examples around with a c# server and python client communicating back and forth.
I'd like to understand how I can instead create a python server and c# client for some interprocess communication.
I managed to find a solution. To begin, I'd first like to clarify some confusing terminology and obscure naming conventions used in dotnet core.
It appears that the NamedPipeServerStream and NamedPipeClientStream don't actually operate on named pipes but instead on unix domain sockets. This means that we must use sockets to communicate between processes rather than FIFO files.
Another frustration I find with dotnet core is that when creating a socket or connecting to one, the NamedPipeServerStream and NamedPipeClientStream classes will add "CoreFxPipe_" to the beginning of the socket name. See related question.
Python Server
#!/usr/bin/python3
import socket
import os
import struct
SOCK_PATH = "/tmp/CoreFxPipe_mySocket"
with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as sock:
try:
os.remove(SOCK_PATH)
except OSError:
pass
sock.bind(SOCK_PATH)
sock.listen()
conn, addr = sock.accept()
with conn:
try:
while True:
amount_expected = struct.unpack('I', conn.recv(4))[0]
print("amount_expected :", amount_expected)
message = conn.recv(amount_expected)
print("Received message : ", message.decode())
# Send data
message_rev = message[::-1].decode()
print("Sent message (reversed) : ", message_rev)
conn.sendall(
struct.pack(
'I',
len(message_rev)
)
+ message_rev.encode('utf-8')
)
except (struct.error, KeyboardInterrupt) as e:
print(e)
finally:
print('closing socket')
C# Client
using System;
using System.IO;
using System.IO.Pipes;
using System.Text;
class PipeClient
{
static void Main(string[] args)
{
using (NamedPipeClientStream pipeClient =
new NamedPipeClientStream(".", "mySocket", PipeDirection.InOut))
{
// Connect to the pipe or wait until the pipe is available.
Console.WriteLine("Attempting to connect to pipe...");
pipeClient.Connect();
try
{
// Read user input and send that to the client process.
using (BinaryWriter _bw = new BinaryWriter(pipeClient))
using (BinaryReader _br = new BinaryReader(pipeClient))
{
while (true)
{
//sw.AutoFlush = true;
Console.Write("Enter text: ");
var str = Console.ReadLine();
var buf = Encoding.ASCII.GetBytes(str); // Get ASCII byte array
_bw.Write((uint)buf.Length); // Write string length
_bw.Write(buf); // Write string
Console.WriteLine("Wrote: \"{0}\"", str);
Console.WriteLine("Let's hear from the server now..");
var len = _br.ReadUInt32();
var temp = new string(_br.ReadChars((int)len));
Console.WriteLine("Received from client: {0}", temp);
}
}
}
// Catch the IOException that is raised if the pipe is broken
// or disconnected.
catch (IOException e)
{
Console.WriteLine("ERROR: {0}", e.Message);
}
}
Console.Write("Press Enter to continue...");
}
}
Sources:
https://abgoswam.wordpress.com/2017/07/13/named-pipes-c-python-net-core/
https://realpython.com/python-sockets/
https://unix.stackexchange.com/questions/75904/are-fifo-pipe-unix-domain-socket-the-same-thing-in-linux-kernel

C# socket hangs when receive in loop - python as socket server

I'm familiar with C#, and know some python. Recent days I'm learning the book Programming Python, 4th Edition and have run the very basic socket samples: echo-server.py and echo-client.py
They work well on my Windows, python 3.x.
python server:
from socket import *
myHost = 'localhost'
myPort = 50007
sockobj = socket(AF_INET, SOCK_STREAM)
sockobj.bind((myHost, myPort))
sockobj.listen(5)
while True:
connection, address = sockobj.accept()
print('Server connected by', address)
while True:
data = connection.recv(1024)
if not data: break
connection.send(b'Echo=>' + data)
connection.close()
Now I want to learn socket in C# too, so I wrote a C# .net framework 4.5 socket client, expecting to receive and show what echo-client.py does.
I got the C# demo from msdn and made some refactor to reduce code size.
public static void Main(string[] args)
{
string server = "localhost";
int port = 50007;
string request = "GET / HTTP/1.1\r\nHost: " + server +
"\r\nConnection: Close\r\n\r\n";
Byte[] sent = Encoding.ASCII.GetBytes(request);
Byte[] recv = new Byte[256];
IPHostEntry hostEntry = Dns.GetHostEntry(server);
IPEndPoint ipe = new IPEndPoint(hostEntry.AddressList[1], port);
Socket s =
new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
s.Connect(ipe);
s.Send(sent, sent.Length, 0);
int bytes = 0;
string page = "recived:\r\n";
//do
{
bytes = s.Receive(recv, recv.Length, 0);
page = page + Encoding.ASCII.GetString(recv, 0, bytes);
}
//while (bytes > 0);
Console.WriteLine(page);
Console.WriteLine("result");
Console.ReadKey();
}
My test steps:
If I set up a web site using local IIS, such as
http://localhost:801, then above code can show the homepage html
contents, this means my C# code is working.
Run echo-server.py, and change C# code's port to 50007, then run,
nothing output in console, and application does not exit, if I place a break point within the loop, I can see the loop has only run once. The python server did output some log saying C# is connecting.
Comment do while loop(as commented in code), this time the output is exactly same as echo-client.py(expected).
So I'm wondering what's wrong when I'm using do while loop?

Send CTCP Messages

I'm currently working on a project for an introductory class on C#. The idea is to make a basic irc client that connects to a single channel on a single irc server. Most things have been easy to implement, however, I've hit a brick wall when attempting to send CTCP messages.
The format is supposed to be: PRIVMSG target : /U+0001ACTION message/U+0001
I am able to identify these messages as they come in, using the Unicode control character, but whenever I try to send my own "ACTION message" is received.
Here's the code I'm using to send the message:
private TcpClient irc; //declarations of properties of irc class
private NetworkStream stream;
private string _inputLine;
StreamReader reader;
StreamWriter writer;
public void Connect() //connects to the irc server in _server on port _port
{
irc = new TcpClient(_server, _port);
stream = irc.GetStream();
reader = new StreamReader(stream);
writer = new StreamWriter(stream);
Send("NICK " + Nick);
Send("USER " + Nick + " 0 * :" + Nick);
Listen();
OnConnect();
}
private void button1_Click(object sender, EventArgs e) //method is from a windows form
{
if (txtMessage.Text.StartsWith("/me"))//sends contents of textbox to SendCTCP if it is an action message
{
test.SendCTCP("ACTION " + txtMessage.Text.Remove(0, 3));
OnAction(test.Nick, txtMessage.Text.Remove(0, 3)); //method OnAction is within the widows form and outputs the message in a textbox for messages sent/received to the channel
}
else
{
test.SendMessage(txtMessage.Text);
ChannelTest(test.Nick, txtMessage.Text, null);
}
txtMessage.Text = "";
}
public void SendCTCP(string message) //formats message with /U+0001 characters
{
char control = '\x01';
Send("PRIVMSG " + _channel + " : " + control.ToString() + message + control.ToString());
}
public void Send(string message) //sends message to server using StreamWriter writer
{
writer.WriteLine(message);
writer.Flush();
}
The Send method uses a StreamWriter to send the message to the server.
I've tried with and without the ToString(). I've tried the character itself within the Send block, rather than in control. I've tried every representation of the character I've been able to find, but I've been unable to make it work. Any help would be appreciated.
Sending the test message "/me tests" through the client results, when the server sends it to other clients in the same channel, in the message: IRCTest!IRCTest#mask PRIVMSG #Channel : ACTION tests
Which is interpreted by every client I can find as: : ACTION tests
edit: I've updated the code with, I hope, all the relevant variables and methods
Well, I feel like an idiot, but at least I figured it out. I've changed it to use '\u0001' as the character, and (wait for it. . .) I deleted the space between the : and the control character. It now functions perfectly.

-ERR Exceeded the login limit for a 15 minute period. Reduce the frequency of requests to the POP3 server

using following code i have reading msg from my hotmail account . But sometimes the following error coming . -ERR Exceeded the login limit for a 15 minute period. Reduce the frequency of requests to the POP3 server . can anyone tell me whats the reason for this ? Is that server problem or anything else ? other than pop3 anyother protocol can we use for hotmail?
public string hotmail(string username, string password)
{
string result = "";
string str = string.Empty;
string strTemp = string.Empty;
try
{
TcpClient tcpclient = new TcpClient();
tcpclient.Connect("pop3.live.com", 995);
System.Net.Security.SslStream sslstream = new SslStream(tcpclient.GetStream());
sslstream.AuthenticateAsClient("pop3.live.com");
System.IO.StreamWriter sw = new StreamWriter(sslstream);
System.IO.StreamReader reader = new StreamReader(sslstream);
strTemp = reader.ReadLine();
sw.WriteLine("USER" + " " + username);
sw.Flush();
strTemp = reader.ReadLine();
sw.WriteLine("PASS" + " " + password);
sw.Flush();
strTemp = reader.ReadLine();
string[] numbers = Regex.Split(strTemp, #"\D+");
int a = 0;
foreach (string value in numbers)
{
if (!string.IsNullOrEmpty(value))
{
int i = int.Parse(value);
numbers[a] = i.ToString();
a++;
}
}
sw.WriteLine("RETR" + " " + numbers[0]);
sw.Flush();
strTemp = reader.ReadLine();
while ((strTemp = reader.ReadLine()) != null)
{
if (strTemp == ".")
{
break;
}
if (strTemp.IndexOf("-ERR") != -1)
{
break;
}
str += strTemp;
}
sw.WriteLine("Quit ");
sw.Flush();
result = str;
return result;
}
Catch ( Exception ex)
{}
return result;
}
thanks in advance ..
Any other protocol you can use? Yes, hotmail/outlook.com now supports IMAP.
But the issue with the code here seems to be that you're creating a new TcpClient every time you run this. If you're running it many times in in a row, Outlook.com/Hotmail will eventually complain. It's as if you've got tons of clients from a single source connecting to their server, which is, when it's not testing code, often a sign of email abuse.
TcpClient tcpclient = new TcpClient(); // Hello, new.
tcpclient.Connect("pop3.live.com", 995);
If you've got a lot to do on the server, keep a single connection active longer, and close it up when you're done.
Every time you run the code in your question, you're creating (and not tcpclient.Close()-ing) a connection to pop3.live.com. I usually only get this error when I've had a lot of connections that don't close properly due to errors when I'm messing with my code.
MSDN actually has a decent example for TcpClient, but you might be more interested in another example from SO here. Check out how it uses using, and nests a loop inside.
using (TcpClient client = new TcpClient())
{
client.Connect("pop3.live.com", 995);
while(variableThatRepresentsRunning)
{
// talk to POP server
}
}
By the way, the best advice I can give here is to tell you not to reinvent the wheel (unless you're just having fun playing with the POP server. Throwing commands via TCP can be lots of fun, especially with IMAP).
OpenPop.NET is a great library to handle POP requests in C#, includes a good MIME parser, and, if you're still working on this, should speed you along quite a bit. Its examples page is excellent.
Go to the mail inbox , you may get mail regarding this and accept it. Otherwise Try to give the request after some time. Because google having some restriction to read mail using pop settings.

Convert console.writeline to RichTextBox.AppendText() c#

I have some code that reads the ssid and rssi from multiple access points. However it is a console app and I need to convert it to a winform app.
WlanClient client = new WlanClient();
foreach (WlanClient.WlanInterface wlanIface in client.Interfaces)
{
Wlan.WlanAvailableNetwork[] networks = wlanIface.GetAvailableNetworkList(0);
foreach (Wlan.WlanAvailableNetwork network in networks)
{
Console.WriteLine("Found network with SSID {0} and Siqnal Quality {1}.", GetStringForSSID(network.dot11Ssid), network.wlanSignalQuality);
}
I wish to convert the line that prints the list in the console to a line (or lines) that will print to a rich text box. Everything I have tried has resulted in just printing one entry from the list.
Thanks
EDIT
Thanks for the responses, here's what I went with..
richTextBox1.AppendText("Found network with SSID---" + GetStringForSSID(network.dot11Ssid) + "and Siqnal Quality---" + rssi + "\n")
You have to make sure the Multiline property to true on the RichTextBox (this is the default so it should be). Use the RichTextBox.AppendText() method and make sure you add a newline character to the end of your string.
I assume here that you are building up a list of networks, for multiple string appends, I would advise using a StringBuilder MSDN Link.
Something like this should work:
StringBuilder builder = new StringBuilder();
foreach(Wlan.WlanAvailableNetwork Network network in networks)
{
string ssidString = GetStringForSSID(network.dot11Ssid);
builder.AppendFormat("Found network with SSID {0} and Signal Quality {1}.", ssidString , network.wlanSignalQuality).AppendLine();
}
textBox.Text = builder.ToString();
TextBox.Lines= networks.Select(n => string.Format("Found network with SSID {0} and Signal Quality {1}.", n.dot11Ssid, n.wlanSignalQuality)).ToArray();

Categories