分享一个简单的群聊程序

showjim 2014-04-08 05:04:58
加精
fastCSharp的TCP服务写了一个简单的demo。源码详见demo.chatServer与demo.chatClient项目,服务器端代码
using System;
using System.Collections.Generic;
using System.Threading;
using fastCSharp.setup.cSharp;
using fastCSharp.threading;

namespace fastCSharp.demo.chatServer
{
/// <summary>
/// 服务端
/// </summary>
[fastCSharp.setup.cSharp.tcpServer(IsIdentityCommand = true, IsAsynchronous = true, Host = "127.0.0.1", Port = 12345)]
public partial class server
{
/// <summary>
/// 命令枚举
/// </summary>
private enum command
{
/// <summary>
/// 登陆
/// </summary>
Login,
/// <summary>
/// 退出
/// </summary>
Logout,
/// <summary>
/// 获取用户列表
/// </summary>
GetUsers,
/// <summary>
/// 发送消息
/// </summary>
Send,
/// <summary>
/// 接收消息
/// </summary>
Receive,
}
/// <summary>
/// 用户信息
/// </summary>
private sealed class userInfo
{
/// <summary>
/// 用户名
/// </summary>
public string User;
/// <summary>
/// 用户版本
/// </summary>
public int UserVersion = int.MinValue;
/// <summary>
/// 获取用户列表委托
/// </summary>
public action<asynchronousMethod.returnValue<usersVerison>> OnUserChanged;
/// <summary>
/// 用户消息集合
/// </summary>
public list<message> Messages = new list<message>();
/// <summary>
/// 获取消息委托
/// </summary>
public action<asynchronousMethod.returnValue<message[]>> OnMessage;
}
/// <summary>
/// 用户集合
/// </summary>
private Dictionary<string, userInfo> users = new Dictionary<string, userInfo>();
/// <summary>
/// 用户集合访问锁
/// </summary>
private int userLock;
/// <summary>
/// 用户版本
/// </summary>
private int userVersion;
/// <summary>
/// 用户登陆
/// </summary>
public event action<string> OnLogin;
/// <summary>
/// 用户登陆
/// </summary>
/// <param name="client">客户端标识</param>
/// <param name="user"></param>
/// <returns></returns>
[fastCSharp.setup.cSharp.tcpServer(CommandIentity = (int)command.Login)]
private bool login(tcpBase.client client, string user)
{
if (user.length() != 0)
{
if (userChangeHandle == null) userChangeHandle = userChange;
interlocked.CompareSetSleep0(ref userLock);
try
{
if (!users.ContainsKey(user))
{
users.Add(user, new userInfo { User = user });
client.UserInfo = user;
++userVersion;
task.TinyTask.Add(userChangeHandle, user);
return true;
}
}
finally { userLock = 0; }
}
return false;
}
/// <summary>
/// 用户退出
/// </summary>
public event action<string> OnLogout;
/// <summary>
/// 退出
/// </summary>
/// <param name="client"></param>
[fastCSharp.setup.cSharp.tcpServer(CommandIentity = (int)command.Logout)]
private void logout(tcpBase.client client)
{
string user = (string)client.UserInfo;
userInfo userInfo;
interlocked.CompareSetSleep0(ref userLock);
try
{
if (users.TryGetValue(user, out userInfo)) users.Remove(user);
++userVersion;
}
finally { userLock = 0; }
if (userInfo != null)
{
if (userChangeHandle == null) userChangeHandle = userChange;
task.TinyTask.Add(userChangeHandle, null);
if (userInfo.OnUserChanged != null) userInfo.OnUserChanged(new usersVerison { UserVersion = int.MinValue });
if (userInfo.OnMessage != null) userInfo.OnMessage(userInfo.Messages.toArray());
if (OnLogout != null) task.TinyTask.Add(OnLogout, user);
}
}
/// <summary>
/// 用户列表与版本信息
/// </summary>
[fastCSharp.setup.cSharp.serialize(IsBaseSerialize = true)]
public partial struct usersVerison
{
/// <summary>
/// 用户列表
/// </summary>
public string[] Users;
/// <summary>
/// 用户列表版本
/// </summary>
public int UserVersion;
}
/// <summary>
/// 获取用户列表
/// </summary>
/// <param name="client"></param>
/// <param name="userVersion"></param>
/// <param name="onUserChanged"></param>
[fastCSharp.setup.cSharp.tcpServer(CommandIentity = (int)command.GetUsers, IsAsynchronousCallback = true, IsClientAsynchronous = true, IsClientSynchronous = false)]
private void getUsers(tcpBase.client client, int userVersion, action<asynchronousMethod.returnValue<usersVerison>> onUserChanged)
{
usersVerison usersVerison = new usersVerison();
action<asynchronousMethod.returnValue<usersVerison>> oldOnUserChanged = null;
interlocked.CompareSetSleep0(ref userLock);
try
{
userInfo userInfo;
if (users.TryGetValue((string)client.UserInfo, out userInfo))
{
if (this.userVersion == userVersion)
{
oldOnUserChanged = userInfo.OnUserChanged;
userInfo.OnUserChanged = onUserChanged;
userInfo.UserVersion = userVersion;
onUserChanged = null;
}
else
{
usersVerison.Users = users.Keys.getArray();
usersVerison.UserVersion = this.userVersion;
}
}
else
{
oldOnUserChanged = onUserChanged;
onUserChanged = null;
}
}
finally
{
userLock = 0;
if (onUserChanged != null) onUserChanged(usersVerison);
if (oldOnUserChanged != null) oldOnUserChanged(new usersVerison { UserVersion = int.MinValue });
}
}
/// <summary>
/// 获取用户列表委托集合
/// </summary>
private list<action<asynchronousMethod.returnValue<usersVerison>>> onUserChangeds = new list<action<asynchronousMethod.returnValue<usersVerison>>>();
/// <summary>
/// 获取用户列表委托集合访问锁
/// </summary>
private int onUserChangedLock;
/// <summary>
/// 用户列表更新
/// </summary>
private action<string> userChangeHandle;
/// <summary>
/// 用户列表更新
/// </summary>
/// <param name="user">新增用户名</param>
private void userChange(string user)
{
usersVerison usersVerison = new usersVerison { UserVersion = int.MinValue };
while (userVersion != usersVerison.UserVersion && Interlocked.CompareExchange(ref onUserChangedLock, 1, 0) == 0)
{
try
{
interlocked.CompareSetSleep0(ref userLock);
try
{
usersVerison.Users = users.Keys.getArray();
usersVerison.UserVersion = userVersion;
foreach (userInfo userInfo in users.Values)
{
if (userInfo.UserVersion != userVersion && userInfo.OnUserChanged != null)
{
onUserChangeds.Add(userInfo.OnUserChanged);
userInfo.OnUserChanged = null;
}
}
}
finally { userLock = 0; }
while (userVersion == usersVerison.UserVersion && onUserChangeds.Count != 0)
{
try
{
onUserChangeds.Pop()(usersVerison);
}
catch { }
}
}
finally { onUserChangedLock = 0; }
}
if (user != null && OnLogin != null) OnLogin(user);
}
/// <summary>
/// 消息
/// </summary>
[fastCSharp.setup.cSharp.serialize(IsBaseSerialize = true)]
public partial struct message
{
/// <summary>
/// 发送者
/// </summary>
public string User;
/// <summary>
/// 发送时间
/// </summary>
public DateTime Time;
/// <summary>
/// 发送内容
/// </summary>
public string Message;
}
/// <summary>
/// 发送消息
/// </summary>
public event action<message> OnMessage;
未完待续
...全文
2937 88 打赏 收藏 转发到动态 举报
写回复
用AI写文章
88 条回复
切换为时间正序
请发表友善的回复…
发表回复
showjim 2014-04-30
  • 打赏
  • 举报
回复
引用 87 楼 SzBenQ6917 的回复:
其实我所要的就是客户端里有服务端,服务端里有客户端;可我弄了两天了,都没弄出来;要么就是异常关闭超过三次就再也连不上了,要么就是只能点对点
你这个需求就是P2P,不同的需求,复杂度不同。 如果你的每个客户端之间可以直接两两相连,那么简单的服务端仅负责推送分发变化的客户端IP与端口信息了。接下来如果客户端群体比较大,并且客户端变换频繁,服务器端还是会存在扛不住的情况。这时候需要考虑将客户端组织成一定图状网络结构(我了解过的网络结构只有KAD、跳跃链表这些),服务器端只需要向几个节点(这是一个容错阀值,比如2)分发信息,其它节点让这些节点自己去分发,要尽量做到信息的传送次数小于 节点数*冗余次数(容错阀值,比如2)。 如果你的客户端不能做到直接相连,那么就不要把客户端分级,可以直接连接的(比如没有防火墙的广域网节点、IPv6节点)成为一级节点,把这些节点组织成上面提到的图状结构,有他们复杂信息的转发。其它节点使用长连接挂靠到几个一级节点(容错阀值,比如2)下面,一级节点复杂向这些节点传送信息。接下来的优化就是穿透处理了,把能够穿透的节点也加入到一级节点中。但是不能让一级节点客户端负载太重,必要的时候还是要让其它节点挂接到服务器的。 需要注意的是:这个网络是不稳定,需要使用回复确认机制;这个网络的数据是不安全的,需要数字签名机制。 其实涉及的东西也不多,感觉除了穿透这一块,如果有良好的测试环境,7天半个月应该就能做完。
SzBenQ6917 2014-04-29
  • 打赏
  • 举报
回复
能不能多对多啊?因为我需要一个多对多的,你这个是多点对一点啊
SzBenQ6917 2014-04-29
  • 打赏
  • 举报
回复
引用 86 楼 sbwwkmyd 的回复:
[quote=引用 85 楼 SzBenQ6917 的回复:]能不能多对多啊?因为我需要一个多对多的,你这个是多点对一点啊
如果你是需要服务器端群集,开启TcpRegister服务有个默认的简单的负载均衡功能。 如果你需要P2P,没有这个功能。[/quote] 其实我所要的就是客户端里有服务端,服务端里有客户端;可我弄了两天了,都没弄出来;要么就是异常关闭超过三次就再也连不上了,要么就是只能点对点
showjim 2014-04-29
  • 打赏
  • 举报
回复
引用 85 楼 SzBenQ6917 的回复:
能不能多对多啊?因为我需要一个多对多的,你这个是多点对一点啊
如果你是需要服务器端群集,开启TcpRegister服务有个默认的简单的负载均衡功能。 如果你需要P2P,没有这个功能。
还寝梦佳期 2014-04-19
  • 打赏
  • 举报
回复
等有空了研究研究
风之影子 2014-04-17
  • 打赏
  • 举报
回复
感谢楼主在技术方面的分享和成长。
风之影子 2014-04-17
  • 打赏
  • 举报
回复
我只想说如果不用图形化,那么楼上所说的这么多代码,我接受,但是你要知道加个图形显示,代码的多少,真不好说。 你想想一下一个dos的大小和一个窗口系统的大小,就明白了。
黄河沙smile8 2014-04-17
  • 打赏
  • 举报
回复
好霸气的说,看一下
ar 2014-04-16
  • 打赏
  • 举报
回复
点不亮的黑色 2014-04-16
  • 打赏
  • 举报
回复
  • 打赏
  • 举报
回复
我买的一本工具书上也有,但是运行不起来好坑爹。
my03131302 2014-04-15
  • 打赏
  • 举报
回复
u010285266 2014-04-15
  • 打赏
  • 举报
回复
学习了。。。。。。。。。
u011136775 2014-04-14
  • 打赏
  • 举报
回复
学习了 感谢啊
gezigulugulu 2014-04-14
  • 打赏
  • 举报
回复
可以用,这个问题困恼了我很久,终于解决了。
小白菜2014 2014-04-13
  • 打赏
  • 举报
回复
好多不太懂 帮顶
lx9921 2014-04-12
  • 打赏
  • 举报
回复
参考参考,看看怎样实现的
  • 打赏
  • 举报
回复
共与存 2014-04-12
  • 打赏
  • 举报
回复
pdmaik001 2014-04-12
  • 打赏
  • 举报
回复
加载更多回复(53)

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧