异步tcp通信——APM.ConsoleDemo
APM测试
俗话说麻雀虽小,五脏俱全。apm虽然简单,但是可以实现单机高性能消息推送(可以采用redis、kafka等改造成大型分布式消息推送服务器)。
测试demo:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks; namespace APM.ConsoleDemo
{
class Program
{ static void Main(string[] args)
{
Console.Title = "APM.Core test"; Console.WriteLine("输入1测试APM tcp通讯"); Console.WriteLine("输入2测试APM转发"); var str = Console.ReadLine(); if (!string.IsNullOrEmpty(str) && str != "")
{
APMServer();
APMClient();
APMClient();
}
else
{
Task.Factory.StartNew(() =>
{
Thread.Sleep();
ClientProcess();
});
ServerProcess(true);
}
Console.ReadLine();
} private static APM.Core.Server server;
static void ServerProcess(bool falg = false)
{
Console.WriteLine("server test");
server = new APM.Core.Server(, );
server.OnAccepted += Server_OnAccepted;
server.OnMessage += Server_OnReceived;
server.OnDisConnected += Server_OnDisConnected;
server.OnOnError += Server_OnOnError;
server.Start();
Console.WriteLine("server is running...");
if (falg)
{
while (true)
{
Console.ReadLine();
Console.WriteLine(string.Format("serverinfo[ClientCount:{0},ReceiveCount:{1},SendCount:{2}]", server.ClientCount, server.ReceiveCount, server.SendCount));
}
} } private static APM.Core.Client client;
static void ClientProcess()
{ Console.WriteLine("Client test"); var localIP = GetLocalIp() + ":8889"; Console.WriteLine("Client send test");
client = new APM.Core.Client(Guid.NewGuid().ToString("N"), , localIP);
client.OnConnected += Client_OnConnected;
client.OnMessage += Client_OnMessage;
client.OnDisConnected += Client_OnDisConnected;
client.OnError += Client_OnError;
client.Connect(); Console.Title = "APM Server & Client";
Console.WriteLine("MutiClients test");
for (int i = ; i < ; i++)
{
new APM.Core.Client(Guid.NewGuid().ToString("N"), , localIP).Connect();
} } #region server events
private static void Server_OnAccepted(APM.Core.UserToken remote)
{
Console.WriteLine("收到客户端连接:" + remote.Client.RemoteEndPoint); }
private static void Server_OnReceived(APM.Core.UserToken remote, byte[] data)
{
if (server.ClientCount <= )
{
Console.WriteLine("收到客户端消息:" + remote.Client.RemoteEndPoint + " " + Encoding.UTF8.GetString(data));
}
server.SendMsg(remote, "server:hello " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"));
} private static void Server_OnDisConnected(APM.Core.UserToken remote, Exception ex)
{
Console.WriteLine(string.Format("客户端{0}已断开连接,断开消息:{1}", remote.ID, ex.Message));
} private static void Server_OnOnError(APM.Core.UserToken remote, Exception ex)
{
Console.WriteLine(string.Format("操作客户端{0}异常,断开消息:{1}", remote.ID, ex.Message));
} #endregion #region client events static string msg = "hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohelloh";
private static void Client_OnConnected(APM.Core.Client c)
{
if (c != null)
c.SendMsg(string.Format("client:{0} {1}", msg, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"))); } private static void Client_OnMessage(byte[] data)
{
Console.WriteLine("收到服务器信息:" + Encoding.UTF8.GetString(data));
if (client != null)
client.SendMsg(string.Format("client:{0} {1}", msg, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")));
} private static void Client_OnDisConnected(Exception ex)
{
Console.WriteLine(string.Format("客户端断开连接,断开消息:{0}", ex.Message));
} private static void Client_OnError(Exception ex)
{
Console.WriteLine(string.Format("客户端异常,异常消息:{0}", ex.Message));
} #endregion #region MyRegion
static string GetLocalIp()
{
string hostname = Dns.GetHostName();//得到本机名
//IPHostEntry localhost = Dns.GetHostByName(hostname);//方法已过期,只得到IPv4的地址
IPHostEntry localhost = Dns.GetHostEntry(hostname);
IPAddress localaddr = localhost.AddressList.Where(b => b.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork).Last();
return localaddr.ToString();
}
#endregion #region APM转发
public static void APMServer()
{
Console.WriteLine("APMServer test");
APM.Server.APMServer server = new Server.APMServer(, );
server.OnAccepted += Server_OnAccepted;
server.OnDisConnected += Server_OnDisConnected;
server.OnError += Server_OnOnError;
server.OnMessage += Server_OnMessage;
server.Start();
Console.WriteLine("APMServer 已启动...");
} private static void Server_OnMessage(Core.Extention.Message msg)
{
Console.WriteLine("APMServer 收到并转发消息:ID {0},Sender {1},SessionID {2},SendTick {3}", msg.ID, msg.Sender, msg.SessionID, msg.SendTick);
} public static void APMClient()
{
Console.WriteLine("APMClient test");
var userID = "张三" + new Random((int)DateTime.Now.Ticks).Next(, );
APM.Client.APMClient apmClient = new Client.APMClient(userID, GetLocalIp(), );
apmClient.OnConnected += ApmClient_OnConnected;
apmClient.OnDisConnected += Client_OnDisConnected;
apmClient.OnError += Client_OnError;
apmClient.OnMessage += APMClient_OnMessage;
apmClient.Connect();
Task.Factory.StartNew(() =>
{
while (true)
{
if (apmClient.Connected)
{
apmClient.SendChannelMsg("all", string.Format("client:{0} {1}", msg, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")));
}
Thread.Sleep();
}
});
Console.WriteLine("APMClient:{0} 已连接到服务器", userID);
} private static void ApmClient_OnConnected(Client.APMClient c)
{
c.Subscribe("all");
} private static void APMClient_OnMessage(Core.Extention.Message msg)
{
Console.WriteLine("APMClient 收到消息:ID {0},Sender {1},SessionID {2},SendTick {3}", msg.ID, msg.Sender, msg.SessionID, msg.SendTick);
}
#endregion
}
}
github地址:https://github.com/yswenli/APM
异步tcp通信——APM.Core 服务端概述
异步tcp通信——APM.Core 解包
异步tcp通信——APM.Server 消息推送服务的实现
异步tcp通信——APM.ConsoleDemo
转载请标明本文来源:http://www.cnblogs.com/yswenli/
更多内容欢迎star作者的github:https://github.com/yswenli/APM
如果发现本文有什么问题和任何建议,也随时欢迎交流~
异步tcp通信——APM.ConsoleDemo的更多相关文章
- 异步tcp通信——APM.Server 消息推送服务的实现
消息推送服务 服务器推送目前流行就是私信.发布/订阅等模式,基本上都是基于会话映射,消息对列等技术实现的:高性能.分布式可以如下解决:会话映射可采用redis cluster等技术实现,消息对列可使用 ...
- 异步tcp通信——APM.Core 服务端概述
为什么使用异步 异步线程是由线程池负责管理,而多线程,我们可以自己控制,当然在多线程中我们也可以使用线程池.就拿网络扒虫而言,如果使用异步模式去实现,它使用线程池进行管理.异步操作执行时,会将操作丢给 ...
- 异步tcp通信——APM.Core 解包
TCP通信解包 虽说这是一个老生长谈的问题,不过网上基本很少见完整业务:或多或少都没有写完或者存在bug.接收到的数据包可以简单分成:小包.大包.跨包三种情况,根据这三种情况作相对应的拆包处理,示例如 ...
- c#之异步Socket通信
0.基于上一篇的c#之Socket(同步)通信,在几个大神评论之后,发现是有挺多地方不足的,所以写了一个改进版本的基于c#的异步Socket通信.再加深一下对Socket的使用和理解.其中客户端和服务 ...
- C#网络编程TCP通信实例程序简单设计
C#网络编程TCP通信实例程序简单设计 采用自带 TcpClient和TcpListener设计一个Tcp通信的例子 只实现了TCP通信 通信程序截图: 压力测试服务端截图: 俩个客户端链接服务端测试 ...
- 【Java TCP/IP Socket】基于NIO的TCP通信(含代码)
NIO主要原理及使用 NIO采取通道(Channel)和缓冲区(Buffer)来传输和保存数据,它是非阻塞式的I/O,即在等待连接.读写数据(这些都是在一线程以客户端的程序中会阻塞线程的操作)的时候, ...
- C# TCP应用编程三 异步TCP应用编程
利用TcpListener和TcpClient类在同步方式下接收.发送数据以及监听客户端连接时,在操作没有完成之前一直处于阻塞状态,这对于接受.发送数据量不大的情况或者操作勇士较短的情况下是比较方便的 ...
- TCP通信
//网络套接字编程实例,服务器端,TCP通信. #include <WinSock2.h> #pragma comment(lib,"ws2_32.lib") #inc ...
- 清晰易懂TCP通信原理解析(附demo、简易TCP通信库源码、解决沾包问题等)C#版
目录 说明 TCP与UDP通信的特点 TCP中的沾包现象 自定义应用层协议 TCPLibrary通信库介绍 Demo演示 未完成功能 源码下载 说明 我前面博客中有多篇文章讲到了.NET中的网络编程, ...
随机推荐
- iscc2016-好长的字符串
Vm0wd2QyVkhVWGhVYmxKV1YwZDRXRmxVUm5kVlJscHpXa2M1VjFKdGVGWlZNbmhQWVd4YWMxZHViRmROYWxaeVdWZDRZV014WkhG ...
- Adobe Photoshop CS或者CC卸载不了怎么办?
有木有没有遇到这个问题的同学?使用Adobe Creative Suite CleanerToo工具下载就好了~ 下载地址:http://pan.baidu.com/s/1pJ3aBsn
- [BZOJ 1257] [CQOI2007] 余数之和sum 【数学】
题目链接:BZOJ - 1257 题目分析 首先, a % b = a - (a/b) * b,那么答案就是 sigma(k % i) = n * k - sigma(k / i) * i ( ...
- Comparing randomized search and grid search for hyperparameter estimation
Comparing randomized search and grid search for hyperparameter estimation Compare randomized search ...
- Emag eht htiw Em Pleh
Emag eht htiw Em Pleh This problem is a reverse case of the problem 2996. You are given the output o ...
- 【Linux】鸟哥的Linux私房菜基础学习篇整理(九)
1. quotacheck [-avugfM] [/mount_point]:扫描文件系统并创建Quota配置文件.参数:-a:扫描所有在/etc/mtab内,含有quota支持的文件系统,加上此参数 ...
- UVA-11983-Weird Advertisement(线段树+扫描线)[求矩形覆盖K次以上的面积]
题意: 求矩形覆盖K次以上的面积 分析: k很小,可以开K颗线段树,用sum[rt][i]来保存覆盖i次的区间和,K次以上全算K次 // File Name: 11983.cpp // Author: ...
- 数据结构(左偏树):HDU 1512 Monkey King
Monkey King Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Tota ...
- 杂题 SPOJ MOBILE2 - Mobiles
MOBILE2 - Mobiles no tags You have been asked to buy a gift for your baby brother, Ike. However, yo ...
- ASP.NET网站发布-允许更新此预编译站点 打勾与不打勾的区别
发布网站时在打开的对话框中,有一个选项是至关重要的,那就是“允许更新此预编译站点”: “允许更新此预编译站点”这一项,默认情况下,前面是打上一个√的,至于要不要打上一个√,是可选的,那么,打勾与不打勾 ...