您的位置:首页 > 理论基础 > 计算机网络

包包版网络游戏大厅+桥牌系统 4.终于可以聊天了

2008-07-31 17:51 309 查看
返回目录

有了上一章所搭建的网络通信框架,我们就可以自由发挥了。只要把握好HandShake的顺序,就可以了。比如说我下面要介绍的大厅里的聊天机制,就是通过实现了503和504协议的“有问必答”原理。

重构后的版本,代码在这里下载:PlayCard 2.2

聊天室的截图如下,以下是一个Server端和两个Client端(注意到,kitty是最后登录的,所以看不到先前的聊天信息):

Code

public class MessageEventArgs : EventArgs

{

private string msg;

public string Message

{

get

{

return msg;

}

set

{

msg = value;

}

}

}
 Client类

添加MessageReceived事件

public event EventHandler<MessageEventArgs> MessageReceived;
在BuildText方法中添加对503协议的处理

case "503":

if (MessageReceived != null)

{

ChatMessage meg = (ChatMessage)obj;

MessageEventArgs e = new MessageEventArgs();

e.Message = meg.Message;

MessageReceived(this, e);

}

break;

MainThread类

将OnMessageReceived方法附属到新添加的事件MessageReceived上:

newClient.MessageReceived += OnMessageReceived;
而添加OnMessageReceived方法如下,从而把这条聊天信息转发给所有在线用户:

public void OnMessageReceived(object sender, MessageEventArgs e)

{

//Message sender client

Client temp = (Client)sender;

AddLog(temp.UserName + " :" + e.Message);

ChatMessage chat = new ChatMessage();

chat.Protocol = "504";

chat.UserName = temp.UserName;

chat.Message = e.Message;

byte[] message = SerializationFormatter.GetSerializationBytes(chat);

Client tempClient;

DataTable dt = ClientList.Instance().GetUserList();

foreach (DataRow row in dt.Rows)

{

string uid = (string)row["UserID"];

tempClient = (Client)clientTable[uid];

tempClient.Send(message);

}

}
以上是Client端和Server端的修改,归结出“程咬金三板斧”,以后每次添加新协议都如法炮制:

1.携带新信息的协议,就在CommonClassLibrary类库添加相应的实体类,派生于CommonProtocol基类。

2.永远是Client端先发Request请求,也就是一个单数协议,如501(登录)、503(发聊天消息),以后还会有很多。这是一个主动的动作,来自UI的的操作,注意,这里只发送消息就可以,而不要等待结果——所谓异步编程的思路。让我们再来看一下点击发送按钮的方法:

if (txtMessage.Text.Trim() != "")

{

ChatMessage u = new ChatMessage();

u.Protocol = "503";

u.Message = txtMessage.Text.Trim();

SendText(SerializationFormatter.GetSerializationBytes(u));

txtMessage.Text = "";

}
3.Server端永远是被动的接收来自Client的Request请求——一个单数协议,在BuildText方法中对其进行解析后,触发主线程的相应事件,于是在相应的方法中,发送偶数协议,也就是Response。这里,可能是发给原先Request的Client端(如502协议登录验证结果),也可能是群发给其他Client端(如504协议转发聊天信息)

4.无论Server端还是Client端,都是在BuildText方法中对接收到的数据包进行反序列化,然后根据协议的不同进行不同的处理。以后我们每次添加新协议,都要这里加上case分支语句,注意到Server端处理单数协议,Client处理偶数协议。

相应的,在这些处理模块中,要进行方法回调,从而操作主线程或UI。这里,Server端使用了事件机制;而Client端使用了委托回调机制。

补充:小赵指出我使用了HashTable这个老古董存储client对象不是很好,于是我将其改造为Dictionary<KValue, TValue>范型:

private Dictionary<string, Client> clientTable;

clientTable = new Dictionary<string, Client>();
也许有人会问,游戏大厅需要聊天么?是的,可以没有这个功能。我演示的目的是承上启下,介绍一下在我这个框架下如何轻松地开发新功能,制定一个套路,为下面的大厅通信打下基础。

此外,在Client端,目前还没有显示其他用户进入或离开的消息,以及显示用户列表的功能。

下一章,我要搭建游戏大厅,并对聊天功能进行改进。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐