65.9K
CodeProject 正在变化。 阅读更多。
Home

通过 Comet Ajax 的 Ajax 聊天样本

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.75/5 (7投票s)

2010年4月22日

GPL3

3分钟阅读

viewsIcon

66887

downloadIcon

2383

一篇关于如何通过 PokeIn Comet Ajax 库在几分钟内创建严肃的 Web 应用程序的文章

让我们为您的网站创建一个聊天插件

在网页上提供访客之间的聊天功能显然会很好。 我将尝试解释如何通过 PokeIn 准备这种类型的网页插件。 如果您赶时间,您可以从上面的链接下载示例项目。 这次,我也为 VB.NET 创建了一个示例。 请不要忘记,您需要下载 PokeIn Library 并将其作为对您的项目的引用添加。

ChatSampleCS

我之前在“this”文章中提到了 PokeIn 的入口点。 现在,我想谈谈库的其他部分。

这是我们应用程序的整个Chat

C#

public class ChatApp
{
	public static Dictionary Users = null;
	public static Dictionary Names = null;
	string ClientID;
	string Username;
	
	public ChatApp(string clientId)
	{
		ClientID = clientId;
		Username = "";
	}
	
	~ChatApp()
	{
		lock (Users)
		{
			Users.Remove(ClientID);
		}
		lock (Names)
		{
			Names.Remove(Username);
		} 
	} 
	
	public void SetName(string user_name)
	{
		if (Username != "")
		{
			PokeIn.Comet.CometWorker.SendToClient(ClientID,
                               "alert('You already have an username!');");
			return;
		}
		bool duplicate = false;
		lock (Names)
		{
			duplicate = Names.ContainsKey(user_name);
		}
		if (duplicate)
			PokeIn.Comet.CometWorker.SendToClient(ClientID,
        			"alert('Another user is using the name you choose!
			\\nPlease try another one.');");
		else
		{
			lock (Names)
			{
				Names.Add(user_name, ClientID);
			}

			lock (Users)
			{
				Users.Add(ClientID, user_name);
			}
			Username = user_name;

			PokeIn.Comet.CometWorker.SendToClient(ClientID,
         "UsernameSet('" + PokeIn.Comet.BrowserHelper.SafeParameter(user_name) + "');"); 
		}
	}
	
	public void Send(string message) 
	{
		PokeIn.Comet.CometWorker.SendToAll("ChatMessageFrom('" +
                      PokeIn.Comet.BrowserHelper.SafeParameter(Username) + 
                      "','" + PokeIn.Comet.BrowserHelper.SafeParameter( message ) +
                      "');");
	}
}

VB.NET

Public Class ChatApp
    Private ClientID As String
    Public Shared Names As Dictionary(Of String, String)
    Private Username As String
    Public Shared Users As Dictionary(Of String, String)


    Public Sub New(ByVal clientId As String)
        Me.ClientID = clientId
        Me.Username = ""
    End Sub

    Shared Sub New()
        ChatApp.Users = Nothing
        ChatApp.Names = Nothing
    End Sub

    Protected Overrides Sub Finalize()
        Try
            SyncLock ChatApp.Users
                ChatApp.Users.Remove(Me.ClientID)
            End SyncLock
            SyncLock ChatApp.Names
                ChatApp.Names.Remove(Me.Username)
            End SyncLock
        Finally
            MyBase.Finalize()
        End Try
    End Sub 

    Public Sub Send(ByVal message As String)
        PokeIn.Comet.CometWorker.SendToAll(String.Concat(New String() {
            "ChatMessageFrom('", PokeIn.Comet.BrowserHelper.SafeParameter(Me.Username),
            "','", PokeIn.Comet.BrowserHelper.SafeParameter(message), "');"}))
    End Sub

    Public Sub SetName(ByVal user_name As String)
        If (Me.Username <> "") Then
            PokeIn.Comet.CometWorker.SendToClient(Me.ClientID,
                "alert('You already have an username!');")
        Else
            Dim duplicate As Boolean = False
            SyncLock ChatApp.Names
                duplicate = ChatApp.Names.ContainsKey(user_name)
            End SyncLock
            If duplicate Then
                PokeIn.Comet.CometWorker.SendToClient(Me.ClientID,
           	"alert('Another user is using the name you choose!
		\nPlease try another one.');")
            Else
                SyncLock ChatApp.Names
                    ChatApp.Names.Add(user_name, Me.ClientID)
                End SyncLock
                SyncLock ChatApp.Users
                    ChatApp.Users.Add(Me.ClientID, user_name)
                End SyncLock
                Me.Username = user_name
                PokeIn.Comet.CometWorker.SendToClient(Me.ClientID,
           	("UsernameSet('" & PokeIn.Comet.BrowserHelper.SafeParameter
			(user_name) & "');"))
            End If
        End If
    End Sub 
End Class

对于每个新连接,PokeIn 都会使用连接的clientId创建此类的实例。 因此,ChatApp类存储此信息并等待用户名。 客户端通过SetName函数调用发送用户名,并且如果Users字典中没有相同的用户名,则客户端会收到UsernameSet事件。 在此之后,Client可以调用Send函数将消息发送给其他人。

正如您所看到的,我们为 Web 应用程序创建了一个管理器类,就像为桌面应用程序一样。

让我们关注代码的某些部分。

为什么我要为字符串参数调用“PokeIn.Comet.BrowserHelper.SafeParameter”函数?

C#

PokeIn.Comet.CometWorker.SendToClient(ClientID, "UsernameSet('" + 
    PokeIn.Comet.BrowserHelper.SafeParameter(user_name) + "');"); 

VB.NET

PokeIn.Comet.CometWorker.SendToClient(Me.ClientID, 
    ("UsernameSet('" & PokeIn.Comet.BrowserHelper.SafeParameter(user_name) & "');")) 

正如您从第一篇文章中了解到的,SendToClient函数将消息发送到浏览器端以运行。 因此,每个消息可能在其自己的函数参数列表中都有一个string参数。 并且这些参数的值可能包含一些对我们的 JavaScript 函数体有害的字符。 为了轻松地消除这些类型的错误,我们可以使用此方法。

为什么我们在类中使用了析构函数?

C#

~ChatApp()
{
	lock (Users)
	{
		Users.Remove(ClientID);
	}
	lock (Names)
	{
		Names.Remove(Username);
	} 
}

VB.NET

Protected Overrides Sub Finalize()
	Try
		SyncLock ChatApp.Users
			ChatApp.Users.Remove(Me.ClientID)
		End SyncLock
		SyncLock ChatApp.Names
			ChatApp.Names.Remove(Me.Username)
		End SyncLock
	Finally
		MyBase.Finalize()
	End Try
End Sub 

如果用户关闭聊天窗口,我们需要安全地将他从我们的活动用户列表中删除,以释放资源和可用名称。 因此,当 PokeIn 意识到用户离线时,它将删除客户端拥有的对象实例。 在此示例中,我们的类析构函数将运行,我们可以从我们的列表中删除用户信息。

Lock / SyncLock 是做什么用的?

Users”和“Names”字典可供所有活动用户并发使用(不要忘记!我们创建了一个多用户应用程序)。 因此,为了线程安全,我们锁定了共享对象。 因此我们知道整个应用程序可以安全地访问共享字典。 如果您下载了示例应用程序,您可能会看到我每次使用这些共享对象时都对其进行了锁定。

技巧

  • PokeIn.Comet.BrowserHelper.RedirectPage:允许您将给定的客户端重定向到给定的 URL(对踢人有用?:)),即,您可以跟踪每个客户端的聊天活动,并通过将他们的页面远程到您的应用程序主页等来踢掉他们。或者某些服务器操作可能需要刷新所有客户端页面。
  • PokeIn.Comet.BrowserHelper.SetElementProperty:您可以从服务器端设置任何客户端对象的任何属性。
    将有一些客户端元素需要直接从服务器端代码进行更改。
  • PokeIn.Comet.BrowserHelper.SetElementEvent:您可以从服务器端侦听客户端元素事件(非常有用?)
    您可以使用此方法轻松准备自动完成控件。

因此,请告诉我您想要的关于 PokeIn 库和/或 Comet Ajax 的文章。 ;)

历史

  • 2010 年 4 月 22 日:首次发布
© . All rights reserved.