Smark.Net实现简单聊天程序
2009-08-18 13:58
405 查看
最近一直和Asterisk打交道,所以又写起了Socket tcp。Smark.Net是基于Socket Tcp封装的组件,主要用途是简化Socket tcp通讯的实现;已经使用它来实现了Asterisk的管理程序和AGI接管程序,以下使用Smark.Net实现一个简单的聊开程序。该程序主要分为两部分,一部分是服务端另一部分就是客户端;信息通过服务端转发到相关客户端。先看下实现的效果图再细讲每端的实现。
服务端
定义服务构建监听程序:
private Smark.Net.Server<Smark.Net.Messages.XMLClient<Smark.Net.Messages.XMLMessageAnalyse>> mServer =
new Smark.Net.Server<Smark.Net.Messages.XMLClient<Smark.Net.Messages.XMLMessageAnalyse>>();
Smark.Net.Server是一个Socket Tcp的服务类,它的泛参描述这个服务是用于那个IClient的实现,XMLClient是一个实现对象,它的泛参是描述这个Client的数据分包实现。
定义相关事件:
mServer.Coding = Encoding.UTF8;
mServer.ClientDisposed += (o, c) => {
Invoke(new Action<Smark.Net.IClient>(ClientClose), c.Client);
};
mServer.ClientConnected += (o, c) => {
Smark.Net.Messages.XMLClient<Smark.Net.Messages.XMLMessageAnalyse> msgclient
= (Smark.Net.Messages.XMLClient<Smark.Net.Messages.XMLMessageAnalyse>)c.Client;
msgclient.MessageReceive += MessageReceive;
msgclient.Receive<Chats.Services.SelectUser>(SelectUser);
msgclient.Receive<Chats.Services.Say>(Say);
msgclient.Receive<Chats.Services.Login>(Login);
};
mServer.Open("192.168.1.128", 9120,50);
在相关事件定义了服务端的编码,还有客户端接入和退出的一些相关事件。在客户端接入事件中还分别定义了一个数据接收事件。
MessageReceive事件:
if (e.Message is Chats.Services.Login)
{
Chats.Services.Login login = (Chats.Services.Login)e.Message;
if (mClients.FindIndex(item => { return item.Name == login.UserName; }) >= 0)
{
e.Client.Send(new Chats.Services.Failure{ Error="用户已经存在!", ID= e.Message.ID});
e.Client.Dispose();
}
else{
e.Client["Logined"] =login.UserName;
e.Client.Name = login.UserName;
e.Client.Send(new Chats.Services.Success { ID= e.Message.ID});
}
}
else
{
if (e.Client["Logined"] == null)
e.Client.Dispose();
}
在消息总接收事件里,对是否登陆的用户进行处理;如果没有登陆就进行其他消息发送的情况直接把连接关闭。
SelectUser消息接收:
Chats.Services.ListUsers lu = new Chats.Services.ListUsers();
lu.ID = select.ID;
foreach (Smark.Net.IClient item in GetClients())
{
lu.Users.Add(item.Name);
}
lu.Send(client);
当收到SelectUser消息时,把当前的所有连接发送回相关请求客户端。
Login消息接收:
private void Login(Smark.Net.Messages.IXMLClient client, Chats.Services.Login msg)
{
Smark.Net.IClient[] clients = GetClients();
foreach (Smark.Net.IClient item in clients)
{
if (item != client)
{
item.Send(msg);
}
}
}
登陆消息处理主要是告诉其他连接的说你已经登陆。
Say消息接收:
private void Say(Smark.Net.Messages.IXMLClient client, Chats.Services.Say say)
{
Smark.Net.IClient[] clients = GetClients();
foreach (Smark.Net.IClient item in clients)
{
if (say.To.FindIndex(c => { return c == item.Name; }) >= 0)
{
item.Send(say);
}
}
}
根据Say消息的接收人对当前连接进行匹配并发送。
客户端
连接到服务端器并定义相关消息接收事件
mConnection = Smark.Net.Server<Smark.Net.Messages.XMLClient<Smark.Net.Messages.XMLMessageAnalyse>>.CreateClient("192.168.1.128", 9120);
mConnection.Coding = Encoding.UTF8;
mConnection.Receive<Chats.Services.ListUsers>((c, msg) => {
Invoke(new Action<Chats.Services.ListUsers>(ListUser), msg);
});
mConnection.Receive<Chats.Services.Login>((c, msg) =>
{
Invoke(new Action<Chats.Services.Login>(Login), msg);
});
mConnection.Receive<Chats.Services.Logout>((c, msg) =>
{
Invoke(new Action<Chats.Services.Logout>(Logout), msg);
});
mConnection.Receive<Chats.Services.Say>((c, msg) =>
{
Invoke(new Action<Chats.Services.Say>(Say), msg);
});
mConnection.Receive();
相关代码和服务端相关不多,当连接建立后就定义相关消息接收事件来处理相关信息。
登陆并获取其他用户信息
Login login = new Login();
login.UserName = txtName.Text;
login.Send(mConnection, msg => {
if (msg is Failure)
{
MessageBox.Show(((Failure)msg).Error);
}
else
{
mConnection.Name = txtName.Text;
Chats.Services.SelectUser select = new SelectUser();
select.Send(mConnection);
cmdLogin.Enabled = false;
}
});
消息处理和发送
private void ListUser(Chats.Services.ListUsers lst)
{
foreach (string item in lst.Users)
{
if (item != mConnection.Name)
stringBindingSource.Add(item);
}
}
private void cmdSendAll_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(txtSend.Text))
{
Chats.Services.Say say = new Say();
foreach (string item in mUsers)
{
say.To.Add(item);
}
say.From = mConnection.Name;
say.Text = txtSend.Text;
say.Send(mConnection);
Say(say);
}
}
private void cmdSend_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(txtSend.Text))
{
Chats.Services.Say say = new Say();
foreach (string item in lstClients.SelectedItems)
{
say.To.Add(item);
}
say.From = mConnection.Name;
say.Text = txtSend.Text;
say.Send(mConnection);
Say(say);
}
}
Smark.Net是一个开源的组件感兴趣的朋友可以访问Google Code获取源码和该程序的源码。
服务端
定义服务构建监听程序:
private Smark.Net.Server<Smark.Net.Messages.XMLClient<Smark.Net.Messages.XMLMessageAnalyse>> mServer =
new Smark.Net.Server<Smark.Net.Messages.XMLClient<Smark.Net.Messages.XMLMessageAnalyse>>();
Smark.Net.Server是一个Socket Tcp的服务类,它的泛参描述这个服务是用于那个IClient的实现,XMLClient是一个实现对象,它的泛参是描述这个Client的数据分包实现。
定义相关事件:
mServer.Coding = Encoding.UTF8;
mServer.ClientDisposed += (o, c) => {
Invoke(new Action<Smark.Net.IClient>(ClientClose), c.Client);
};
mServer.ClientConnected += (o, c) => {
Smark.Net.Messages.XMLClient<Smark.Net.Messages.XMLMessageAnalyse> msgclient
= (Smark.Net.Messages.XMLClient<Smark.Net.Messages.XMLMessageAnalyse>)c.Client;
msgclient.MessageReceive += MessageReceive;
msgclient.Receive<Chats.Services.SelectUser>(SelectUser);
msgclient.Receive<Chats.Services.Say>(Say);
msgclient.Receive<Chats.Services.Login>(Login);
};
mServer.Open("192.168.1.128", 9120,50);
在相关事件定义了服务端的编码,还有客户端接入和退出的一些相关事件。在客户端接入事件中还分别定义了一个数据接收事件。
MessageReceive事件:
if (e.Message is Chats.Services.Login)
{
Chats.Services.Login login = (Chats.Services.Login)e.Message;
if (mClients.FindIndex(item => { return item.Name == login.UserName; }) >= 0)
{
e.Client.Send(new Chats.Services.Failure{ Error="用户已经存在!", ID= e.Message.ID});
e.Client.Dispose();
}
else{
e.Client["Logined"] =login.UserName;
e.Client.Name = login.UserName;
e.Client.Send(new Chats.Services.Success { ID= e.Message.ID});
}
}
else
{
if (e.Client["Logined"] == null)
e.Client.Dispose();
}
在消息总接收事件里,对是否登陆的用户进行处理;如果没有登陆就进行其他消息发送的情况直接把连接关闭。
SelectUser消息接收:
Chats.Services.ListUsers lu = new Chats.Services.ListUsers();
lu.ID = select.ID;
foreach (Smark.Net.IClient item in GetClients())
{
lu.Users.Add(item.Name);
}
lu.Send(client);
当收到SelectUser消息时,把当前的所有连接发送回相关请求客户端。
Login消息接收:
private void Login(Smark.Net.Messages.IXMLClient client, Chats.Services.Login msg)
{
Smark.Net.IClient[] clients = GetClients();
foreach (Smark.Net.IClient item in clients)
{
if (item != client)
{
item.Send(msg);
}
}
}
登陆消息处理主要是告诉其他连接的说你已经登陆。
Say消息接收:
private void Say(Smark.Net.Messages.IXMLClient client, Chats.Services.Say say)
{
Smark.Net.IClient[] clients = GetClients();
foreach (Smark.Net.IClient item in clients)
{
if (say.To.FindIndex(c => { return c == item.Name; }) >= 0)
{
item.Send(say);
}
}
}
根据Say消息的接收人对当前连接进行匹配并发送。
客户端
连接到服务端器并定义相关消息接收事件
mConnection = Smark.Net.Server<Smark.Net.Messages.XMLClient<Smark.Net.Messages.XMLMessageAnalyse>>.CreateClient("192.168.1.128", 9120);
mConnection.Coding = Encoding.UTF8;
mConnection.Receive<Chats.Services.ListUsers>((c, msg) => {
Invoke(new Action<Chats.Services.ListUsers>(ListUser), msg);
});
mConnection.Receive<Chats.Services.Login>((c, msg) =>
{
Invoke(new Action<Chats.Services.Login>(Login), msg);
});
mConnection.Receive<Chats.Services.Logout>((c, msg) =>
{
Invoke(new Action<Chats.Services.Logout>(Logout), msg);
});
mConnection.Receive<Chats.Services.Say>((c, msg) =>
{
Invoke(new Action<Chats.Services.Say>(Say), msg);
});
mConnection.Receive();
相关代码和服务端相关不多,当连接建立后就定义相关消息接收事件来处理相关信息。
登陆并获取其他用户信息
Login login = new Login();
login.UserName = txtName.Text;
login.Send(mConnection, msg => {
if (msg is Failure)
{
MessageBox.Show(((Failure)msg).Error);
}
else
{
mConnection.Name = txtName.Text;
Chats.Services.SelectUser select = new SelectUser();
select.Send(mConnection);
cmdLogin.Enabled = false;
}
});
消息处理和发送
private void ListUser(Chats.Services.ListUsers lst)
{
foreach (string item in lst.Users)
{
if (item != mConnection.Name)
stringBindingSource.Add(item);
}
}
private void cmdSendAll_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(txtSend.Text))
{
Chats.Services.Say say = new Say();
foreach (string item in mUsers)
{
say.To.Add(item);
}
say.From = mConnection.Name;
say.Text = txtSend.Text;
say.Send(mConnection);
Say(say);
}
}
private void cmdSend_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(txtSend.Text))
{
Chats.Services.Say say = new Say();
foreach (string item in lstClients.SelectedItems)
{
say.To.Add(item);
}
say.From = mConnection.Name;
say.Text = txtSend.Text;
say.Send(mConnection);
Say(say);
}
}
Smark.Net是一个开源的组件感兴趣的朋友可以访问Google Code获取源码和该程序的源码。
相关文章推荐
- java-用java.net.Socket和java.net.ServerSocket实现简单的聊天程序
- java swing实现简单的socket通讯聊天程序源码
- 使用最新Netty实现一个简单的聊天程序
- 用Socket做简单聊天程序(VB.net)
- 一个简单的AJAX实现,基于C#的ASP.Net,包括服务器端的程序代码
- 简单的网络聊天程序,MFC实现
- linux下TCP/IP实现简单聊天程序
- 简单快速开发C\S架构程序用最简单的不分层最快的效率达到功能要求的例子程序FrmCommnetList 所有评论列表的功能实现
- java实现简单TCP聊天程序
- C#实现简单聊天程序的方法
- 使用最新Netty实现一个简单的聊天程序
- 套接字(socket)编程简单实现server-client聊天程序
- c#实现类似QQ的简单聊天程序,可支持广域网。
- Python基于Socket实现的简单聊天程序示例
- android Socket实现简单聊天小程序
- Android客户端简单的聊天程序实现
- Python实现最简单的双人聊天程序
- C#实现简单聊天程序的方法
- 使用Ajax long polling实现简单的聊天程序
- 基于socket实现的简单的聊天程序