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.
Related
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
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?
I have two applications. The server send files to my clients. The clients are implemented in Unity3d with C#. Each client has one thread to receive files from server. If I send the files over the network, I write the bytes to the file with this code:
private Thread clientThread;
private object writeLock = new object();
public void StartConnection()
{
// Start connection to server.
clientThread = new Thread(GetFiles);
}
public void GetFiles()
{
string fullPath;
// Receive bytes from server
fullPath = Path.Combine(clientDirPath, fileNameFromServer);
lock(writeLock)
{
using (BinaryWriter bWrite = new BinaryWriter(File.Open(fullPath, FileMode.Create)))
{
bWrite.Write(binaryFileContent);
bWrite.Flush();
}
}
Now, if I start multple clients and send files to receive them synchronously on the client-side, I get this error message: System.IO.IOException:Sharing violation on path. Whether I use the lock-statement it is not working. Do anyone know the way to get it working?
EDIT: I added more code.
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.
I wrote a program to download files from a website by using WebClient.DownloadFile().
public static void downWeb()
{
WebClient myWebClient = new WebClient();
path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
if (add() == 1)
{
Console.WriteLine("Response is " + add());
Console.WriteLine("Downloading File = " + dynFileName + "....");
myWebClient.DownloadFile(fullAddress, (path + dynFileName));
}
}
public static int add()
{
string url = fullAddress;
WebRequest webRequest = WebRequest.Create(url);
WebResponse webResponse;
try
{
webResponse = webRequest.GetResponse();
}
catch
{
return 0;
}
return 1;
}
downWeb() is a function to be called in the Main() function.
add() is a function that tests the availability of the file on server. If response is positive, it returns value "1".
fullAddress = address from where the files has to downloaded. It's changing every time before calling this function in a loop present in Main().
When I start my application, I ask the user to:
1) Enter URL to be downloaded i.e. www.1234.com\samplefiles\pg-1.pdf
2) Number of pages to be downloaded (By changing the above filename no. in a loop as rest of the url is same on server)
Now my problem is when I am downloading files, first file downloads PERFECTLY, but the second download is never finished. It says "REQUEST TIMED OUT", and my application closes.
I don't know what's happening here.
How can this be solved?
http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.getresponse.aspx
You must call the Close method to close the stream and release the connection. Failure to do so may cause your application to run out of connections.
Your problem likely is related to the fact that you do not dispose of your connections. You should make sure that you don't leak them.