Windows Phone 8.1 IRC

Jaz*_*rix 5 c# sockets irc windows-phone-8.1

我一直在尝试为我的Windows Phone 8.1应用程序创建一个IRC客户端,我很幸运能找到一个非常好的教程.不幸的是,该教程是针对WP 7的,而且从WP 8.1开始,MS将其更改为运行时应用程序,这意味着SocketAsyncEvents我无法使用(即使MSDN说它支持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);
}
Run Code Online (Sandbox Code Playgroud)

挖掘我发现套接字被移动到Windows.Networking.Sockets,但它们都没有包含SocketAsyncEvents.

我几乎无法再从这里开始了,有没有人知道如何将所述功能转换为适用于WP 8.1的功能?

Jaz*_*rix 4

开始!

经过大量研究后,我发现:

首先我们有一个连接方法。

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;

}
Run Code Online (Sandbox Code Playgroud)

为了读取通过 StreamSocket 接收的数据,我们创建一个 ReadData() 方法并使其递归,以便我们继续获取数据:

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();
}
Run Code Online (Sandbox Code Playgroud)

现在我们有两种新方法,SendIdentity();通常ReplyPong(string message); IRC 服务器会 ping 你,这里你必须用 pong 回复,如下所示:

private void ReplyPong(string message) {
    var pingCode = Regex.Match(message, "[0-9]+");
    SendRawMessage("PONG :" + pingCode);
}
Run Code Online (Sandbox Code Playgroud)

当服务器准备好时,我们还必须发送我们的身份,如下所示:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

最后我们有了将SendRawMessage();数据发送到服务器的方法。

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;
}
Run Code Online (Sandbox Code Playgroud)

差点忘了 dispose 函数,当你想关闭流时可以调用它:)

public void Dispose()
{
     SendRawMessage("QUIT :");
     _closing = true;
}
Run Code Online (Sandbox Code Playgroud)

这将发送最后一条消息,表明我们要离开,并且由于 _close now 为 true,因此该流将在之后被处理。