I've been trying to make an IRC client for my Windows Phone 8.1 app, and I was lucky enough to find a really good tutorial. Unfortunately the tutorial was for WP 7 and as of WP 8.1 MS changed it to runtime apps, meaning SocketAsyncEvents
is unavailable to me (even though MSDN says it supports Windows Phone 8.1).
public void SendToServer(string message)
{
var asyncEvent = new SocketAsyncEventArgs { RemoteEndPoint = new DnsEndPoint(server, serverPort) };
var buffer = Encoding.UTF8.GetBytes(message + Environment.NewLine);
asyncEvent.SetBuffer(buffer, 0, buffer.Length);
connection.SendAsync(asyncEvent);
}
Digging around I found that the sockets were moved to Windows.Networking.Sockets, but yet none of them contained SocketAsyncEvents
.
I'm pretty much unable to go any further from here, does anybody have an idea on how to convert said function to something that would work with WP 8.1?
Here goes!
After a lot of research this is what I found:
First of all we got a connect method.
private readonly StreamSocket _clientSocket;
private bool _connected;
private DataReader _dataReader;
public string Hostname {
get;
set;
}
public int Port {
get;
set;
}
public Credentials Credentials;
public readonly string Channel;
public async Task < bool > Connect() {
if (_connected) return false;
var hostname = new HostName(Hostname);
await _clientSocket.ConnectAsync(hostname, Port.ToString());
_connected = true;
_dataReader = new DataReader(_clientSocket.InputStream) {
InputStreamOptions = InputStreamOptions.Partial
};
ReadData();
return true;
}
To read the data we receive through the StreamSocket, we create a ReadData() method and make it recursive so we will continue to get the data:
async private void ReadData() {
if (!_connected || _clientSocket == null) return;
uint s = await _dataReader.LoadAsync(2048);
string data = _dataReader.ReadString(s);
if (data.Contains("No ident response")) SendIdentity();
if (Regex.IsMatch(data, "PING :[0-9]+\\r\\n")) ReplyPong(data);
ReadData();
}
Now we have two new methods, SendIdentity();
and ReplyPong(string message);
Usually the IRC server will ping you, here you have to reply with a pong, like so:
private void ReplyPong(string message) {
var pingCode = Regex.Match(message, "[0-9]+");
SendRawMessage("PONG :" + pingCode);
}
And we also have to send our identity when the server is ready for it, like so:
private void SendIdentity() {
if (Credentials.Nickname == string.Empty) Credentials.Nickname = Credentials.Username;
SendRawMessage("NICK " + Credentials.Nickname);
SendRawMessage("USER " + Credentials.Username + " " + Credentials.Username + " " + Credentials.Username + " :" + Credentials.Username);
if (Credentials.Password != String.Empty) SendRawMessage("PASS " + Credentials.Password);
}
public class Credentials {
public string Nickname {
get;
set;
}
public string Username {
get;
set;
}
public string Password {
get;
set;
}
public Credentials(string username, string password = "", string nickname = "") {
Username = username;
Password = password;
Nickname = nickname;
}
}
At last we have our SendRawMessage();
method, that sends data to the server.
async private void SendRawMessage(string message) {
var writer = new DataWriter(_clientSocket.OutputStream);
writer.WriteString(message + "\r\n");
await writer.StoreAsync();
await writer.FlushAsync();
writer.DetachStream();
if (!_closing) return;
_clientSocket.DisposeSafe();
_connected = false;
}
Almost forgot out dispose function, which you can call when you want to close the stream :)
public void Dispose()
{
SendRawMessage("QUIT :");
_closing = true;
}
This will send a last message indicating that we're leaving, and since _closing now is true, the stream will be disposed afterwards.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With