xe 最大连接数限制、记录客户连接、心跳
xe 最大连接数限制、记录客户连接、心跳
//author: cxg
unit DSServerContainer;
interface
uses
SysUtils, Classes, IniFiles, Windows, Provider, DBClient,
DSTCPServerTransport,
DSServer, DSCommonServer, DB, ADODB, Generics.Collections, DSService,
DBXDataSnap, DBXCommon, DSHTTPLayer, DBXinterbase, forms, DbxCompressionFilter
,IdTCPConnection ,IdWinsock2, ExtCtrls
;
type
TTCP_KeepAlive = record
OnOff: Cardinal;
KeepAliveTime: Cardinal; // 多长时间(ms)没有数据就开始send心跳包
KeepAliveInterval: Cardinal; // 每隔多长时间(ms)send一个心跳包,发5次(系统值)
end;
TServerContainer1 = class(TDataModule)
DSServer1: TDSServer;
DSTCPServerTransport1: TDSTCPServerTransport;
DSServerClass1: TDSServerClass;
procedure DSServerClass1GetClass(DSServerClass: TDSServerClass;
var PersistentClass: TPersistentClass);
procedure DataModuleCreate(Sender: TObject);
procedure DSServer1Disconnect(DSConnectEventObject: TDSConnectEventObject);
procedure DSServer1Connect(DSConnectEventObject: TDSConnectEventObject);
private
{ Private declarations }
end;
var
ServerContainer1: TServerContainer1;
implementation
uses ServerMethodsUnit1,MainForm;
{$R *.dfm}
procedure TServerContainer1.DataModuleCreate(Sender: TObject);
begin
DSServer1.AutoStart :=False;
DSTCPServerTransport1.Port :=g_port;
DSServer1.Start;
end;
procedure TServerContainer1.DSServer1Connect(
DSConnectEventObject: TDSConnectEventObject);
var
ClientConnection: TIdTCPConnection;
Val: TTCP_KeepAlive;
Ret: DWord;
begin
// 最大连接数量限制,验证来访者密码
if (DSConnectEventObject.ChannelInfo = nil) or
(g_CurrentConnNum >= FrmMain.MaxclientNum) or
(DSConnectEventObject.ConnectProperties[TDBXPropertyNames.UserName] <> g_username) or
(DSConnectEventObject.ConnectProperties[TDBXPropertyNames.Password] <> g_userpassword) then
begin
DSConnectEventObject.DbxConnection.Destroy;
Exit;
end
else
begin
inc(g_currentconnnum); // 记录来访者数量
//把心跳包放到服务端上执行,如果服务器的某个TCP连接在5秒钟没有收到数据,
//将会发送向对端发送心跳包,间隔3秒钟,连续发送5次。如果5次以后对端还没有应答,服务器将结束该TCP连接
ClientConnection := TIdTCPConnection(DSConnectEventObject.ChannelInfo.Id);
Val.OnOff := 1;
Val.KeepAliveTime := 5000;
Val.KeepAliveInterval := 3000;
WSAIoctl(ClientConnection.Socket.Binding.Handle, IOC_IN or IOC_VENDOR or 4,
@val, SizeOf(val), nil, 0, @Ret, nil, nil);
end;
//记录客户连接
with FrmMain do
begin
dsShowDataSet.Append;
dsShowDataSet.FindField('ClientConnect').AsDateTime := Time;
if DSConnectEventObject.ChannelInfo <> nil then
begin
dsShowDataSet.FindField('ClientId').AsInteger := DSConnectEventObject.ChannelInfo.Id;
dsShowDataSet.FindField('ClientIp').AsString := ClientConnection.Socket.Binding.PeerIP +
':' + IntToStr(ClientConnection.Socket.Binding.PeerPort);
dsShowDataSet.FindField('ServerIp').AsString := ClientConnection.Socket.Binding.IP + ':' +
IntToStr(ClientConnection.Socket.Binding.Port);
end;
dsShowDataSet.FindField('ClientUserName').AsString := DSConnectEventObject.ConnectProperties
[TDBXPropertyNames.UserName];
dsShowDataSet.FindField('ClientUserPassword').AsString :=
DSConnectEventObject.ConnectProperties[TDBXPropertyNames.Password];
dsShowDataSet.FindField('ServerInfo').AsString := '上线';
dsShowDataSet.Post;
end;
end;
procedure TServerContainer1.DSServer1Disconnect(
DSConnectEventObject: TDSConnectEventObject);
var
ClientConnection: TIdTCPConnection;
begin
//记录客户下线
with FrmMain do
begin
dsShowDataSet.Append;
dsShowDataSet.FindField('ClientDisConn').AsDateTime := Time;
if DSConnectEventObject.ChannelInfo <> nil then
begin
ClientConnection := TIdTCPConnection(DSConnectEventObject.ChannelInfo.Id);
dsShowDataSet.FindField('ClientId').AsInteger := DSConnectEventObject.ChannelInfo.Id;
dsShowDataSet.FindField('ClientIp').AsString := ClientConnection.Socket.Binding.PeerIP +
':' + IntToStr(ClientConnection.Socket.Binding.PeerPort);
dsShowDataSet.FindField('ServerIp').AsString := ClientConnection.Socket.Binding.IP + ':' +
IntToStr(ClientConnection.Socket.Binding.Port);
end;
dsShowDataSet.FindField('ClientUserName').AsString := DSConnectEventObject.ConnectProperties
[TDBXPropertyNames.UserName];
dsShowDataSet.FindField('ClientUserPassword').AsString :=
DSConnectEventObject.ConnectProperties[TDBXPropertyNames.Password];
dsShowDataSet.FindField('ServerInfo').AsString := '下线';
dsShowDataSet.Post;
end;
Dec(g_CurrentConnNum);
end;
procedure TServerContainer1.DSServerClass1GetClass(
DSServerClass: TDSServerClass; var PersistentClass: TPersistentClass);
begin
PersistentClass := ServerMethodsUnit1.TServerMethods1;
end;
end.
xe 最大连接数限制、记录客户连接、心跳的更多相关文章
- 第十九篇:不为客户连接创建子进程的并发回射服务器(select实现)
前言 在此前,我已经介绍了一种并发回射服务器实现.它通过调用fork函数为每个客户请求创建一个子进程.同时,我还为此服务器添加了自动消除僵尸子进程的机制.现在请想想,在客户量非常大的情况下,这种为每个 ...
- 不为客户连接创建子进程的并发回射服务器( select实现 )
前言 在此前,我已经介绍了一种并发回射服务器实现( 点此进入 ).它通过调用fork函数为每个客户请求创建一个子进程.同时,我还为此服务器添加了自动消除僵尸子进程的机制.现在请想想,在客户量非常大的情 ...
- [转]Android TCP长连接 心跳机制及实现
背景知识 智能手机上的长连接心跳和在Internet上的长连接心跳有什么不同 Android系统的推送和iOS的推送有什么区别 几种推送的实现方式 协议 1XMPP简介 2 MQTT简介 3移动端消息 ...
- 转 互联网推送服务原理:长连接+心跳机制(MQTT协议)
http://blog.csdn.net/zhangzeyuaaa/article/details/39028369 目录(?)[-] 无线移动网络的特点 android系统的推送和IOS的推送有什么 ...
- 互联网推送服务原理:长连接+心跳机制(MQTT协议)
互联网推送消息的方式很常见,特别是移动互联网上,手机每天都能收到好多推送消息,经过研究发现,这些推送服务的原理都是维护一个长连接(要不不可能达到实时效果),但普通的socket连接对服务器的消耗太大了 ...
- 第二十篇:不为客户连接创建子进程的并发回射服务器(poll实现)
前言 在上文中,我使用select函数实现了不为客户连接创建子进程的并发回射服务器( 点此进入 ).但其中有个细节确实有点麻烦,那就是还得设置一个client数组用来标记select监听描述符集中被设 ...
- 移动互联网消息推送原理:长连接+心跳机制(MQTT协议)
互联网推送消息的方式很常见,特别是移动互联网上,手机每天都能收到好多推送消息,经过研究发现,这些推送服务的原理都是维护一个长连接(要不不可能达到实时效果),但普通的socket连接对服务器的消耗太大了 ...
- vsftp客户连接常见故障现象
ftp客户连接常见故障现象现象0:> ftp: connect :连接被拒绝原因: 服务没启动解决: # chkconfig vsftpd on<Enter> 现象1:500 OOP ...
- 不为客户连接创建子进程的并发回射服务器( poll实现 )
前言 在上文中,我使用select函数实现了不为客户连接创建子进程的并发回射服务器( 点此进入 ).但其中有个细节确实有点麻烦,那就是还得设置一个client数组用来标记select监听描述符集中被设 ...
随机推荐
- tcp连接的建立与释放
1.TCP是面向连接的协议. 运输连接时用来传送TCP报文的.TCP运输连接的建立和释放是每一次面向连接的通信中必不可少的过程.因此,运输链接就有三个阶段,即:连接建立.数据传送和连接释放. 在TCP ...
- Python基础笔记系列三:list列表
本系列教程供个人学习笔记使用,如果您要浏览可能需要其它编程语言基础(如C语言),why?因为我写得烂啊,只有我自己看得懂!! python中的list列表是一种序列型数据类型,一有序数据集合用逗号间隔 ...
- 新东方雅思词汇---7.4、cap
新东方雅思词汇---7.4.cap 一.总结 一句话总结: 抓住 capable 英 ['keɪpəb(ə)l] 美 ['kepəbl] adj. 能干的,能胜任的:有才华的 词组短语 capab ...
- 四十二 Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)的mget和bulk批量操作
注意:前面讲到的各种操作都是一次http请求操作一条数据,如果想要操作多条数据就会产生多次请求,所以就有了mget和bulk批量操作,mget和bulk批量操作是一次请求可以操作多条数据 1.mget ...
- idea结合git使用
1.下载安装好git.exe2. 2.安装好以后在cmd输入git 3.在idea配置git环境 4.托管项目到码云 5.登录码云官网,地址就是你在码云注册的账号和密码
- nyoj-5-kmp裸题
题目链接: http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=5 kmp统计匹配串出现次数,贼尴尬好久没做字符串题目,一开始求得是文本串的next ...
- 【Python】unicode' object is not callable
在Python中,出现'unicode' object is not callable的错误一般是把字符串当做函数使用了.
- 【nyoj-1274】信道安全(SPFA)
题目链接:http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=1274 题目描述 Alpha 机构有自己的一套网络系统进行信息传送.情报员 A 位于 ...
- 【lightoj-1002】Country Roads(dijkstra变形)
light1002:传送门 [题目大意] n个点m条边,给一个源点,找出源点到其他点的‘最短路’ 定义:找出每条通路中最大的cost,这些最大的cost中找出一个最小的即为‘最短路’,dijkstra ...
- jenkins-启动和关闭服务
笔者没有把Jenkins配置到tomcat中,每次都是用命令行来启动Jenkins.但是遇到一个问题:Jenkins一直是开着的,想关闭也关闭不了.百度了一些资料,均不靠谱(必须吐槽一下百度).于是进 ...