Socks 协议是一种代理 (Proxy) 协议, 例如我们所熟知的 Shdowsocks 便是 Socks 协议的一个典型应用程序, Socks 协议有多个版本, 目前最新的版本为 5, 其协议标准文档为 RFC 1928。
我们一起来使用.net 7 构建一个支持用户管理的高性能socks5代理服务端
VERSION | METHODS_COUNT | METHODS |
---|---|---|
1字节 | 1字节 | 1到255字节,长度zMETHODS_COUNT |
0x05 | 0x03 | 0x00 0x01 0x02 |
METHODS列表(其他的认证方法可以自行上网了解)
VERSION | METHOD |
---|---|
1字节 | 1字节 |
0x05 | 0x00 |
VERSION | METHOD |
---|---|
1字节 | 1字节 |
0x05 | 0x02 |
VERSION | USERNAME_LENGTH | USERNAME | PASSWORD_LENGTH | PASSWORD |
---|---|---|---|---|
1字节 | 1字节 | 1到255字节 | 1字节 | 1到255字节 |
0x01 | 0x01 | 0x0a | 0x01 | 0x0a |
VERSION | STATUS |
---|---|
1字节 | 1字节 |
0x01 | 0x00 |
VERSION | COMMAND | RSV | ADDRESS_TYPE | DST.ADDR | DST.PORT |
---|---|---|---|---|---|
1字节 | 1字节 | 1字节 | 1字节 | 1-255字节 | 2字节 |
VERSION | RESPONSE | RSV | ADDRESS_TYPE | DST.ADDR | DST.PORT |
---|---|---|---|---|---|
1字节 | 1字节 | 1字节 | 1字节 | 1-255字节 | 2字节 |
第3步成功后,进入数据转发阶段
RSV | FRAG | ADDRESS_TYPE | DST.ADDR | DST.PORT | DATA |
---|---|---|---|---|---|
2字节 | 1字节 | 1字节 | 可变长 | 2字节 | 可变长 |
从协议中我们可以看出,一个Socks5协议的连接需要经过握手,认证(可选),建立连接三个流程。那么这是典型的符合状态机模型的业务流程。
创建状态和事件枚举
public enum ClientState
{
Normal,
ToBeCertified,
Certified,
Connected,
Death
}
public enum ClientStateEvents
{
OnRevAuthenticationNegotiation, //当收到客户端认证协商
OnRevClientProfile, //收到客户端的认证信息
OnRevRequestProxy, //收到客户端的命令请求请求代理
OnException,
OnDeath
}
根据服务器是否配置需要用户名密码登录,从而建立正确的状态流程。
if (clientStatehandler.NeedAuth)
{
builder.In(ClientState.Normal)
.On(ClientStateEvents.OnRevAuthenticationNegotiation)
.Goto(ClientState.ToBeCertified)
.Execute<UserToken>(clientStatehandler.HandleAuthenticationNegotiationRequestAsync)
.On(ClientStateEvents.OnException)
.Goto(ClientState.Death);
}
else
{
builder.In(ClientState.Normal)
.On(ClientStateEvents.OnRevAuthenticationNegotiation)
.Goto(ClientState.Certified)
.Execute<UserToken>(clientStatehandler.HandleAuthenticationNegotiationRequestAsync)
.On(ClientStateEvents.OnException)
.Goto(ClientState.Death);
}
builder.In(ClientState.ToBeCertified)
.On(ClientStateEvents.OnRevClientProfile)
.Goto(ClientState.Certified)
.Execute<UserToken>(clientStatehandler.HandleClientProfileAsync)
.On(ClientStateEvents.OnException)
.Goto(ClientState.Death); ;
builder.In(ClientState.Certified)
.On(ClientStateEvents.OnRevRequestProxy)
.Goto(ClientState.Connected)
.Execute<UserToken>(clientStatehandler.HandleRequestProxyAsync)
.On(ClientStateEvents.OnException)
.Goto(ClientState.Death);
builder.In(ClientState.Connected).On(ClientStateEvents.OnException).Goto(ClientState.Death);
在状态扭转中如果出现异常,则直接跳转状态到“Death”,
_machine.TransitionExceptionThrown += async (obj, e) =>
{
_logger.LogError(e.Exception.ToString());
await _machine.Fire(ClientStateEvents.OnException);
};
对应状态扭转创建相应的处理方法, 基本都是解析客户端发来的数据包,判断是否合理,最后返回一个响应。
/// <summary>
/// 处理认证协商
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
/// <exception cref="InvalidOperationException"></exception>
public async Task HandleAuthenticationNegotiationRequestAsync(UserToken token)
{
if (token.ClientData.Length < 3)
{
await token.ClientSocket.SendAsync(new byte[] { 0x05, _exceptionCode });
throw new ArgumentException("Error request format from client.");
}
if (token.ClientData.Span[0] != 0x05) //socks5默认头为5
{
await token.ClientSocket.SendAsync(new byte[] { 0x05, _exceptionCode });
throw new ArgumentException("Error request format from client.");
}
int methodCount = token.ClientData.Span[1];
if (token.ClientData.Length < 2 + methodCount) //校验报文
{
await token.ClientSocket.SendAsync(new byte[] { 0x05, _exceptionCode });
throw new ArgumentException("Error request format from client.");
}
bool supprtAuth = false;
for (int i = 0; i < methodCount; i++)
{
if (token.ClientData.Span[2 + i] == 0x02)
{
supprtAuth = true;
break;
}
}
if (_serverConfiguration.NeedAuth && !supprtAuth) //是否支持账号密码认证
{
await token.ClientSocket.SendAsync(new byte[] { 0x05, _exceptionCode });
throw new InvalidOperationException("Can't support password authentication!");
}
await token.ClientSocket.SendAsync(new byte[] { 0x05, (byte)(_serverConfiguration.NeedAuth ? 0x02 : 0x00) });
}
/// <summary>
/// 接收到客户端认证
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
public async Task HandleClientProfileAsync(UserToken token)
{
var version = token.ClientData.Span[0];
//if (version != _serverConfiguration.AuthVersion)
//{
// await token.ClientSocket.SendAsync(new byte[] { 0x05, _exceptionCode });
// throw new ArgumentException("The certification version is inconsistent");
//}
var userNameLength = token.ClientData.Span[1];
var passwordLength = token.ClientData.Span[2 + userNameLength];
if (token.ClientData.Length < 3 + userNameLength + passwordLength)
{
await token.ClientSocket.SendAsync(new byte[] { 0x05, _exceptionCode });
throw new ArgumentException("Error authentication format from client.");
}
var userName = Encoding.UTF8.GetString(token.ClientData.Span.Slice(2, userNameLength));
var password = Encoding.UTF8.GetString(token.ClientData.Span.Slice(3 + userNameLength, passwordLength));
var user = await _userService.FindSingleUserByUserNameAndPasswordAsync(userName, password);
if (user == null || user.ExpireTime < DateTime.Now)
{
await token.ClientSocket.SendAsync(new byte[] { version, _exceptionCode });
throw new ArgumentException($"User{userName}尝试非法登录");
}
token.UserName = user.UserName;
token.Password = user.Password;
token.ExpireTime = user.ExpireTime;
await token.ClientSocket.SendAsync(new byte[] { version, 0x00 });
}
/// <summary>
/// 客户端请求连接
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
public async Task HandleRequestProxyAsync(UserToken token)
{
var data = token.ClientData.Slice(3);
Socks5CommandType socks5CommandType = (Socks5CommandType)token.ClientData.Span[1];
var proxyInfo = _byteUtil.GetProxyInfo(data);
var serverPort = BitConverter.GetBytes(_serverConfiguration.Port);
if (socks5CommandType == Socks5CommandType.Connect) //tcp
{
//返回连接成功
IPEndPoint targetEP = new IPEndPoint(proxyInfo.Item2, proxyInfo.Item3);//目标服务器的终结点
token.ServerSocket = new Socket(targetEP.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
token.ServerSocket.Bind(new IPEndPoint(IPAddress.Any, 0));
var e = new SocketAsyncEventArgs
{
RemoteEndPoint = new IPEndPoint(targetEP.Address, targetEP.Port)
};
token.ServerSocket.ConnectAsync(e);
e.Completed += async (e, a) =>
{
try
{
token.ServerBuffer = new byte[800 * 1024];//800kb
token.StartTcpProxy();
var datas = new List<byte> { 0x05, 0x0, 0, (byte)Socks5AddressType.IPV4 };
foreach (var add in (token.ServerSocket.LocalEndPoint as IPEndPoint).Address.GetAddressBytes())
{
datas.Add(add);
}
//代理端启动的端口信息回复给客户端
datas.AddRange(BitConverter.GetBytes((token.ServerSocket.LocalEndPoint as IPEndPoint).Port).Take(2).Reverse());
await token.ClientSocket.SendAsync(datas.ToArray());
}
catch (Exception)
{
token.Dispose();
}
};
}
else if (socks5CommandType == Socks5CommandType.Udp)//udp
{
token.ClientUdpEndPoint = new IPEndPoint(proxyInfo.Item2, proxyInfo.Item3);//客户端发起代理的udp终结点
token.IsSupportUdp = true;
token.ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
token.ServerSocket.Bind(new IPEndPoint(IPAddress.Any, 0));
token.ServerBuffer = new byte[800 * 1024];//800kb
token.StartUdpProxy(_byteUtil);
var addressBytes = (token.ServerSocket.LocalEndPoint as IPEndPoint).Address.GetAddressBytes();
var portBytes = BitConverter.GetBytes((token.ServerSocket.LocalEndPoint as IPEndPoint).Port).Take(2).Reverse().ToArray();
await token.ClientSocket.SendAsync(new byte[] { 0x05, 0x0, 0, (byte)Socks5AddressType.IPV4, addressBytes[0], addressBytes[1], addressBytes[2], addressBytes[3], portBytes[0], portBytes[1] });
}
else
{
await token.ClientSocket.SendAsync(new byte[] { 0x05, 0x1, 0, (byte)Socks5AddressType.IPV4, 0, 0, 0, 0, 0, 0 });
throw new Exception("Unsupport proxy type.");
}
}
当服务器采用需要认证的配置时,我们会返回给客户端0x02的认证方式,此时,客户端需要上传用户名和密码,如果认证成功我们就可以将用户信息与连接对象做绑定,方便后续管理。
在客户端通过tcp或者udp上传数据包,需要代理服务器转发时,我们记录数据包的大小作为上传数据包流量记录下来,反之亦然。
示例:记录tcp代理客户端的下载流量
public void StartTcpProxy()
{
Task.Run(async () =>
{
while (true)
{
var data = await ServerSocket.ReceiveAsync(ServerBuffer);
if (data == 0)
{
Dispose();
}
await ClientSocket.SendAsync(ServerBuffer.AsMemory(0, data));
if (!string.IsNullOrEmpty(UserName))
ExcuteAfterDownloadBytes?.Invoke(UserName, data);
}
}, CancellationTokenSource.Token);
}
当管理界面修改某用户的密码或者过期时间的时候
1.修改密码,强制目前所有使用该用户名密码的连接断开
2.我们每个连接会有一个定时服务,判断是否过期
从而实现用户下线。
//更新密码或者过期时间后
public void UpdateUserPasswordAndExpireTime(string password, DateTime dateTime)
{
if (password != Password)
{
Dispose();
}
if (DateTime.Now > ExpireTime)
{
Dispose();
}
}
/// <summary>
/// 过期自动下线
/// </summary>
public void WhenExpireAutoOffline()
{
Task.Run(async () =>
{
while (true)
{
if (DateTime.Now > ExpireTime)
{
Dispose();
}
await Task.Delay(1000);
}
}, CancellationTokenSource.Token);
}
用户数据包括,用户名密码,使用流量,过期时间等存储在server端的sqlite数据库中。通过EFcore来增删改查。
如下定期更新用户流量到数据库
private void LoopUpdateUserFlowrate()
{
Task.Run(async () =>
{
while (true)
{
var datas = _uploadBytes.Select(x =>
{
return new
{
UserName = x.Key,
AddUploadBytes = x.Value,
AddDownloadBytes = _downloadBytes.ContainsKey(x.Key) ? _downloadBytes[x.Key] : 0
};
});
if (datas.Count() <= 0
|| (datas.All(x => x.AddUploadBytes == 0)
&& datas.All(x => x.AddDownloadBytes == 0)))
{
await Task.Delay(5000);
continue;
}
var users = await _userService.Value.GetUsersInNamesAsync(datas.Select(x => x.UserName));
foreach (var item in datas)
{
users.FirstOrDefault(x => x.UserName == item.UserName).UploadBytes += item.AddUploadBytes;
users.FirstOrDefault(x => x.UserName == item.UserName).DownloadBytes += item.AddDownloadBytes;
}
await _userService.Value.BatchUpdateUserAsync(users);
_uploadBytes.Clear();
_downloadBytes.Clear();
await Task.Delay(5000);
}
});
}
//批量更新用户信息到sqlite
public async Task BatchUpdateUserFlowrateAsync(IEnumerable<User> users)
{
using (var context = _dbContextFactory.CreateDbContext())
{
context.Users.UpdateRange(users);
await context.SaveChangesAsync();
}
}
打开服务
打开Proxifier配置到我们的服务
查看Proxifier已经流量走到我们的服务
服务端管理器
http://github.com/BruceQiu1996/Socks5Server
年前,小编打算写一套SAS绘图的宏程序,于是在朋友圈发了个“调查问卷”,询问了大家临床编程中常遇见的图形。经过漫长的积累与等待(究其原因还是太懒了),本文孕育与诞生了,小编将在本文及后续推文中汇总并分享一些常见的SAS绘图程序及技巧。图形类型折线图散点图条形图箱体图蜘蛛图 泳道图 瀑布图 生存图小编最初的想法是将这些图形的绘制写成宏,然后分享/出售,日前,看到了《药物临床试验数据递交指导原则(征求意见稿).doc》正文114行的“尤其应避免大型宏程序的嵌套”,所以写宏的计划暂时夭折了。所以呀,今天要分享的内容不含大型宏程序。折线图首先是最基础的折线图,折线图的应有也是十分广泛的,譬如:药时曲线等均是临床试验中折线图绘制的典型例子。关于这部分小编也是在历史文章写过的,如有兴趣可在本文阅读完后,在此点击进行阅读(药时(一)、药时(二)),当然这是几年前的文章了,文中不乏有漏洞或程序冗杂之处。如有需要小编后来多次更新的最新相关程序,可私下联系。SGPLOTGTL procformat; valueGROUPfmt1='高剂量组'2='中剂量组'3=
分类专栏:Python接口自动化测试之requests库入门 作者|Anthony_tester,300w+访问量博主,Oracle测试开发工程师。地址|https://blog.csdn.net/u011541946/article/details/77745924声明|本文是Anthony原创,已获授权发布,未经原作者允许请勿转载我们可能听说了Session和Cookies,面试中可能也会被问到这个两者之间的区别。本篇主要通过画图来理解两个机制,然后通过回到两个机制的不同来结束整个Requests的学习。1.为什么需要Session和Cookie我们知道HTTP是一种无状态的响应。上一个请求和下一个请求没有任何关系。但是现实过程中,需要这些请求之间有关系。例如,你在首页登录,但是进入到列表页就显示没有登录,点击一个数据提示你还需要登录。为了解决这样问题,需要两个机制,那就是Session和Cookie 2.Cookies机制原理 浏览器第一次发送请求,没有带cookies,服务器收到之后,在数据库找,找到有相关权限。服务器就给出相应,并设置一个cookie。浏览器收到服务器发送
作者|AdrianColyer译者|Monanfei出品|AI科技大本营(ID:rgznai100)本文是一篇有趣的论文(150successfulmachinelearningmodels:6lessonslearnedatBooking.comBernadietal.,KDD’19),通过分析Booking.com上150个成功的面向客户的机器学习应用程序的集成,该论文对其中的经验教训进行了精彩的总结,主要内容如下:使用机器学习模型的项目将带来巨大的商业价值模型表现并不代表商业绩效明确你要解决的问题预测服务的延迟很重要尽早获得有关模型质量的反馈使用随机对照试验测试模型对业务的影响不仅如此,本文更是包含超过这6条之外的建议。我们发现,推动真正的业务影响非常困难,而且很难隔离和理解建模工作与观察到的影响之间的联系……我们的主要结论是,构建机器学习支持的150种成功产品有一个基础,那就是一个与其他学科相结合的,迭代的,受假设驱动的过程。请千万不把上面的话理解成投资机器学习是不值得的,恰恰相反,在面向用户的场景中,锻炼设计、构建和实施成功的机器学习模型的能力,这正是组织竞争力的基础。场景
fork是一个拥有50年历史的陈年系统调用,它是一个传奇!时至今日,它依旧灿烂。 一个程序员可以永远不用read/write,也可以不懂mmap,但必须懂fork。这是一种格调!fork没有参数,它是如此简单,是UNIX哲学的布道者或者说卫道者们的首选,它被写进了几乎每一本操作系统教科书里,成了创建新进程的绝佳范式,fork站在原地,似乎在闭着眼睛蔑视Windows的CreateProcess,它的参数是如此之多,如此之复杂,在UNIX的世界,简单就是一切!然而UNIX却不是整个世界!似乎在对立的另一面,响荡着不同的声音,fork看起来是如此诡异,颠覆了初学者的认知,并且,fork开销巨大...如果你知道fork开销巨大,那为何不用clone呢??诚然,clone并非标准,且参数多,复杂,麻烦,不美观,不雅致,看上去并不是很符合UNIX的价值观...本文就站在上述这个对立面的立场,为fork再泼一盆冷水。fork是的C语言教科书没法安安静静地讲fork,因为fork不符合C函数的调用规范。C语言和操作系统原本就是两门正交的课程,你可以认为它们是无关的,C函数可以在没有操作系统的单片机上
你应该知道的6种加密货币(它们都不是比特币)智能时刻2018-03-0515:08在21世纪,货币不再局限于纸币、硬币和信用卡。事实上,一些钱确实是国际性的,不是由任何特定的政府所拥有,而是由“人民”来管理,而不是一个中央实体。它也完全存在于互联网上。这种货币被称为加密货币。几年前,比特币首次流行时,你可能听说过或甚至使用过比特币,但比特币曾用于规定,其他加密货币现在被用来支付家庭成员的午餐费用,向客户收取产品和服务的费用,并进行其他日常交易。作为一名企业家,关注最常用的加密货币是很重要的。这里有六个我想你应该知道的。Ethereum与其像许多其他加密货币一样与比特币竞争,Ethereum补充了它;当比特币区块链网络跟踪自己货币的所有权时,Ethereum区块链为其用户的应用程序运行编程代码。人们使用Ethereum来创建定制的(但值得信任的)众筹平台、独立的在线组织,甚至是他们自己的加密货币。由于这些应用程序是分散的,它们只能在Ethereum网络中构建。虽然以太,这个网络的钱,并不是用来支付日常支付的,任何有价值的东西都可以用来交易产品和服务;因此,许多开发人员在构建应用程序时使用
大数据文摘编译作品,欢迎个人转发朋友圈;其他机构、自媒体转载,务必后台留言,申请授权。 荐文专家招募:如果你是业界专家, 如果你的工作和数据有关, 更重要的是,如果你能够找到好文章并愿意与读者分享, 请点击文末“阅读原文”,加入我们! 荐文一旦采纳,我们会在文章开头致谢并宣传。荐文专家|孙强资深生物信息专家,现在服务于美国国立癌症研究所,从事癌症基因组数据库管理工作。作者|AlexandraOssola翻译|土家校对|徐丽玲导读建立DNA搜索引擎的竞赛---基因组搜索公司争相成为个性化医疗的谷歌! 自2005年,二代测序开始改变遗传学领域的研究。获得个人的全基因组测序变得快速且相对廉价。遗传信息数据库正在以TB字节的速度增长,医生和研究人员迫切需要一种有效的信息筛选方法,以寻找某种异常的原因或者为评估患者对治疗措施的反应提供线索。 在过去的五年,研发DNA搜索引擎的公司如雨后春笋般涌现,争相成为研发DNA搜索引擎的第一人。他们都有不同的战术——有些甚至拥有自己私有的遗传信息数据库,但是大多数正致力于链接足够多的遗传数据库,以便用户可以快速识别大量的各种各样的突变。大多数公司也研究应用生
AI科技评论按:本文由图普科技工程师翻译自《Neuralnetworkspromisesharpesteverimages》,AI科技评论独家首发文章。上图向我们分别展示了一个原始星系的图像(左边第一张),经过退化处理了的星系图像(左起第二张),经GAN修复的星系图像(左起第三张),以及之前的最先进的技术——“反卷积”技术加工完成的星系图像(右边第一张)。天文望远镜是天文学使用的主要仪器,通常情况下会受到其自身镜片或镜头大小的限制。望远镜在很大程度上会受到其镜头或镜片的直径,也就是所谓的“光圈”,的限制。简单来说,镜头直径越大,望远镜能集中的光就越多,天文学家对微小物体的侦探和观察就越清楚。那奎斯特抽样定理(又称采样定理)对分辨率的限制问题进行了阐述,该定理说明采样频率与信号频谱之间的关系。KevinSchawinski,苏黎世联邦理工学院的教授,带领着他的瑞士研究团队,使用当前最新的机器学习技术去挑战望远镜的“光圈限制”。他们向神经网络输入能模仿大脑神经元的计算方法,以及星系的具体形象,然后让神经网络自动恢复一张模糊的图像,把它变成一张清晰的图像。跟人类一样,神经网络也是需要通过一些
导读大数据是原材料,机器学习是原材料加工厂,而新一代人工智能服务则是工厂出炉的产品被消费在越来越多的日常生活中。在Deepmind和AlphaGo获得的巨大成功吸引了全世界的目光的同时,新一代人工智能德比大战已经开始。Deepmind之前开发的玩雅达利(Atari)街机游戏的人工智能是全新一代的智能技术——大数据驱动通用人工智能(BigData-drivenArtificialGeneralIntelligence)。就像这个名字所提到的,这里有两个重要的因素,一是“大数据”驱动,二是通用人工智能。大数据驱动的机器学习使得机器尽量脱离人类的经验指导,自动在海量数据和工作环境中挖掘知识取得进步。而通用人工智能基于端对端(end-to-end)的深度强化学习(DeepReinforcementLearning),帮助机器能在不同的任务中共享一套学习框架,无需人类进一步调试。这两个因素同时作用出一个效果,即人需要的干预越来越少,而机器在与环境交互反馈中的自主学习比重越来越大。“大数据”驱动的机器学习AlphaGo的围棋棋力来自于30万张人类对弈棋谱以及3千万次自我对弈,这是一个典型的大数据机
大家好,又见面了,我是你们的朋友全栈君。 RJ45接口通常用于数据传输,最常见的应用为网卡接口。RJ45是各种不同接头的一种类型(例如:RJ11也是接头的一种类型,不过它是电话上用的)。 RJ45头根据线的排序不同,分为有两种T568A,T568B,T568B是橙白、橙、绿白、蓝、蓝白、绿、棕白、棕;T568A是绿白、绿、橙白、蓝、蓝白、橙、棕白、棕;因此使用RJ45接头的线也有两种即:直通线、交叉线。常见的RJ45接口有两类:用于以太网网卡、路由器以太网接口等的DTE类型,还有用于交换机等的DCE类型。 DTE我们可以称做“数据终端设备”,DCE我们可以称做“数据通信设备”。从某种意义来说,DTE设备称为“主动通信设备”,DCE设备称为“被动通信设备”。当两个类型一样的设备使用RJ45接口连接通信时,必须使用交叉线连接。这个可以从如下的RJ45DTE类型引脚定义和RJ45DCE类型引脚定义来说明:从上图中我们可以看出,如果DTE类型接口和DTE类型接口相连不交叉相连引脚的话,对触的引脚都是数据接收(发送)引脚,势必通信将不能进行。另外需要说明:一些DCE类型设备会和对端自动协商,此
在编写Servlet时,往往只重写了doGet和doPost方法,使用Tomcat通过(HttpServletRequest和HttpServletResponse)接口传递来的request和response对象来处理请求并作出响应,因为学习(HttpServletRequestWrapper和HttpServletResponseWrapper)而引发request和response究竟是哪来的的思考,所以控制台输出了一下他们的类: System.out.println(request.getClass()); System.out.println(response.getClass()); 复制 结果如下: classorg.apache.catalina.connector.RequestFacade classorg.apache.catalina.connector.ResponseFacade 复制 由包名可以看出,这两个类并不是javaservlet标准中的实现类,于是去Tomcat官网查看了API文档。 RequestFacade和ResponseF
题目 题目链接:https://codeforces.com/problemset/problem/379/F 有一颗\(4\)个节点的树,\(2,3,4\)号节点的父亲节点都是\(1\)。\(m\)次操作。操作有\(1\)种: u:设现在这颗树有\(n\)个节点,则您要新建两个节点\(n+1,n+2\)并让它们变为\(u\)的儿子节点(连一条\(u\)到\(n+1\)的边和\(u\)到\(n+2\)的边)。保证\(u\)是叶子节点。进行完操作后,您要输出此时树的直径。 \(1\lem\le5\times10^5\)。 思路 首先每次操作最多只会让直径增加\(1\)。那么如果原来直径两端是\(x,y\),这次加入点后直径增加了,那么\(x,n+1\)与\(y,n+1\)中至少有一个会成为新的直径两端。 所以只需要倍增求一下LCA就可以了。 时间复杂度\(O(m\logm)\)。 代码 #include<bits/stdc++.h> usingnamespacestd; constintN=1000010,LG=20; intm,x,y,f[N][LG+1],dep[N
★Tox是什么 一个反窥探的开源项目;一种基于DHT(BitTorrent)技术的即时通讯协议;一个为安全而生的加密通讯系统。美国棱镜计划曝光后,一个名为irungentoo的牛人于17天后的2013年6月23日在Github上发起该项目,目标是为大众提供安全且便捷的沟通。 ★Tox有什么 【加密通讯】——每次会话都使用不同的密码加密,安全无忧,巧妙防破解 【去中心化】——没有服务器存储你的账户信息和会话内容,无从窥探,隐私有保障 【开源免费】——源代码可以自由获取、修改和审查,不用担心软件后门,更不用厌恶广告 ◇加密通讯 不加密的通讯犹如隔空喊话,飘过的人都知道通话内容,下文我们称未加密的通讯内容为【明文】。国内不少应用因为各自的原因,居然极不负责任的直接将明文数据发送出去,非常容易导致消息被有心之人拦截和篡改,各类诈骗事件中所谓技术手段作案屡见不鲜,加密通讯的出现正是为了保护用户,提高安全性。 然而,近年加密聊天的软件可谓层出不穷,面对如今破解效率不断提升,Tox抗破解表现如何呢?Tox采用前向保密(英文:ForwardSecrecy,属于对称加密,细节见下文),其密钥“交换
1.oneteam:可增设标记提醒功能(闹钟),可结合每日课表,每日作业,另外界面颜色需要改善,使其易于区分。 2.FFF团:界面不美观,看着比较繁琐,需要改善,可增加提取微信支付记录功能。 3.扬梦之舟:数据最好存在云端,使其可增设排行榜功能以更好地吸引人使用。 4.盈风战队:内容单一,只有简单图片的简介,功能单一,可增设显示每个教学楼的课程安排,空教室情况查询功能。 5.天码行空:个人认为记账本就不需要登录了吧,毕竟大多数情况是在自己的手机上。如果需要登录,可以修改使其记住密码,不用二次输入。还有课增设时间段的账单总结。 6.逐梦人:预约时可增设选择服务类型(包括注明性别,价位,有无特定理发师......),后台明文传输密码需要改善。 7.口袋小组:优秀,基本无意见,按老师所说,可分设知识体系。 8.凯域软创:界面平淡无奇,需要优化,另外可增加excel表导入功能。 9.灭霸:很优秀,无意见,按老师所说,可细分一下表白墙和二手市场。 10.1234:功能单一,还不是很健全。另外可增设教室座位预约功能。 11.敲什么都队:精确查询可根据实际要求改为模糊查询,宿舍服务(维修申报)可
SDN第一次上机实验 任务一 在Ubuntu系统的home目录下创建一个目录,目录命名为学号 任务二 在创建的目录下,完成Mininet的源码安装。 任务三 使用Mininet可视化工具,生成下图所示的拓扑,并保存拓扑文件名为学号.py 任务四 使用Mininet的命令行生成如下拓扑: 3台交换机,每个交换机连接1台主机,3台交换机连接成一条线 3台主机,每个主机都连接到同1台交换机上 任务五 在4b)的基础上,在Mininet交互界面上新增1台主机并且连接到交换机上,再测试新拓扑的连通性 任务六 编辑(一)中第3步保存的Python脚本,添加如下网络性能限制,生成拓扑: h1的cpu最高不超过50%; h1和s1之间的链路带宽为10,延迟为5ms,最大队列大小为1000,损耗率50。 进阶任务 代码如下 #!/usr/bin/python importjson frommininet.topoimportTopo frommininet.netimportMininet frommininet.nodeimportCPULimitedHost,RemoteCont
TemplateInterpreter::initialize()方法实现如下: 源代码位置:/src/share/vm/interpreter/templateInterpreter.cpp voidTemplateInterpreter::initialize(){ if(_code!=NULL) return; //抽象解释器AbstractInterpreter的初始化,AbstractInterpreter是基于汇编模型的解释器的共同基类, //定义了解释器和解释器生成器的抽象接口 AbstractInterpreter::initialize(); //模板表TemplateTable的初始化,模板表TemplateTable保存了各个字节码的模板 TemplateTable::initialize(); //generateinterpreter { ResourceMarkrm; intcode_size=InterpreterCodeSize; //CodeCache的Stub队列StubQueue的初始化 _code=newStubQueue(newInt
老是找有点烦!直接抄一份存着! $(function(){ //遍历获取的input元素对象数组,绑定click事件 varlen=$("input[type='file']").length; for(vari=0;i<len;i++){ $("input[type='file']").eq(i).click(function(){ $(this).next().val(""); $(this).next().hide(); $(this).css("width","200px"); }) } } 复制 jQuery获取: jQuery.parent(expr),找父亲节点,可以传入expr进行过滤,比如\(("span").parent()或者\)("span").parent(".class") jQuery.parents(expr),类似于jQuery.parents(expr),但是是查找所有祖先元素,不限于父元素 jQuery.children(expr),返回所有子节点,这个方法只会返回直接的孩子节点,不会返回所有的子孙节点 jQuery.contents(),返
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/10766017 AndroidAPIDemos中有很多非常Nice的例子,这些例子的代码都写的很出色,如果大家把APIDemos中的每个例子研究透了,那么恭喜你已经成为一个真正的Android高手了。这也算是给一些比较迷茫的Android开发者一个指出了一个提升自我能力的方向吧。APIDemos中的例子众多,今天我们就来模仿其中一个3D变换的特效,来实现一种别样的图片浏览器。 既然是做中轴旋转的特效,那么肯定就要用到3D变换的功能。在Android中如果想要实现3D效果一般有两种选择,一是使用OpenGLES,二是使用Camera。OpenGLES使用起来太过复杂,一般是用于比较高级的3D特效或游戏,像比较简单的一些3D效果,使用Camera就足够了。 Camera中提供了三种旋转方法,分别是rotateX()、rotateY()和rotateZ,调用这三个方法,并传入相应的角度,就可以让视图围绕这三个轴进行旋转,而今天我们要做的中轴旋转效果其实就是让视图围绕Y轴进行旋转
1.技术难度不是太大,代码大致如下 2.用到的一些第三方 ZFProgressView,pageController,RESideMenu,MJRefresh,MBProgressHUD,RNFrostedSidebar,SDWebImage,SDCycleScrollView等 3.下载地址 https://itunes.apple.com/cn/app/ling-ling-ke/id1059665708?mt=8 4.如果需要源码的可以联系我。 QQ:564578384 决定你人生上限的,不是能力,而是做人做事的格局。你的能力决定你能得到什么,而你的格局,却会决定你最终能走到哪里。我不怀疑你的能力,但我不看好你的人品。
上两篇博客 8皇后以及N皇后算法探究,回溯算法的JAVA实现,递归方案 8皇后以及N皇后算法探究,回溯算法的JAVA实现,非递归,数据结构“栈”实现 研究了递归方法实现回溯,解决N皇后问题,下面我们来探讨一下非递归方案 实验结果令人还是有些失望,原来非递归方案的性能并不比递归方案性能高 代码如下: packagecom.newflypig.eightqueen; importjava.util.Date; /** *使用循环控制来实现回溯,解决N皇后 *@authornewflydd@189.cn *Time:2016年1月1日下午9:37:32 */ publicclassEightQueen4{ privatestaticshortK=15; privatestaticshortN=0; privatestaticbooleandead=false;//下方走到了死路 publicstaticvoidmain(String[]args){ for(N=9;N<=K;N++){ Datebegin=newDate(); dead=false; longcount=0