📄 echoserver.dpr
字号:
program EchoServer;
{$APPTYPE CONSOLE}
uses
SysUtils, windows;
function JSockStart(ThreadID: Integer; Addr: Pchar; Port: Smallint; KeepAlive: Integer; SameIpCount: Integer; pOnJSockConnect: Pointer; pOnJSockReceive: Pointer; pOnJSockSendComplete: Pointer; pOnJSockDisconnect: Pointer; pOnJSockError: Pointer): Integer; stdcall; external 'tcpsrv.dll';
function JSockWork(ThreadID: Integer; TimeOut: Integer): Integer; stdcall; external 'tcpsrv.dll';
function JSockSend(ThreadID: Integer; CliID: Integer; Data: Pchar; Len: Integer; NonBlocking: Integer): Integer; stdcall; external 'tcpsrv.dll';
function JSockDisconnect(ThreadID: Integer; CliID: Integer): Integer; stdcall; external 'tcpsrv.dll';
function JSockStop(ThreadID: Integer): Integer; stdcall; external 'tcpsrv.dll';
var
OnJSockConnectCount: Integer;
OnJSockReceiveCount: Integer;
OnJSockSendCount: Integer;
OnJSockSendCompleteCount: Integer;
OnJSockDisconnectCount: Integer;
OnJSockErrorCount1, OnJSockErrorCount2: Integer;
//限制,最多只能保持65407客户端长连接,一次最多只能发送和接收576个字节的数据
procedure pOnJSockConnect(ThreadID: Integer; CliID: Integer; IIP: Integer) stdcall;
begin
{当有客户端连接时触发该事件;
ThreadID线程序号,主要用户解决多线程共享资源访问问题,这个需要由JSockWork的ThreadID决定
比如两个线程同时调用JSockWork参数ThreadID分别是1和2,这样这里的ThreadID可能是1或2,1标示第一个线程2标示第二个线程
CliID是连接的编号,这个号码是0-79999的一个数字,已存在的连接不会有重复
IIP是客户端的ip地址,可以用函数inet_ntoa转换成字符串ip
}
//JSockDisconnect(ThreadID, CliID); 断开当前连接
InterlockedIncrement(OnJSockConnectCount);
end;
procedure pOnJSockReceive(ThreadID: Integer; CliID: Integer; IIP: Integer; Data: Pchar; Len: Integer) stdcall;
begin
{当收到客户端数据时触发该事件;
ThreadID线程序号,主要用户解决多线程共享资源访问问题,这个需要由JSockWork的ThreadID决定
比如两个线程同时调用JSockWork参数ThreadID分别是1和2,这样这里的ThreadID可能是1或2,1标示第一个线程2标示第二个线程
CliID是连接的编号,这个号码是0-79999的一个数字,已存在的连接不会有重复
IIP是客户端的ip地址,可以用函数inet_ntoa转换成字符串ip
Data是收到的数据内容
Len是收到的数据长度
}
if JSockSend(ThreadID, CliID, Data, Len, 1) > 0 then
InterlockedIncrement(OnJSockSendCount);
{发送数据给连接编号是CliID的客户端;最后一个参数0表示阻塞模式发送,此时不回触发pOnJSockSendComplete事件;
最后一个参数是1表示异步发送,会触发事件pOnJSockSendComplete;建议使用1可以获得更高的效率
返回值大于0表示发送成功
}
//JSockDisconnect(ThreadID, CliID); 断开当前连接
InterlockedIncrement(OnJSockReceiveCount);
end;
procedure pOnJSockSendComplete(ThreadID: Integer; CliID: Integer; IIP: Integer; Data: Pchar; Len: Integer) stdcall;
begin
{当收JSockSend发送数据完毕时触发该事件;
ThreadID线程序号,主要用户解决多线程共享资源访问问题,这个需要由JSockWork的ThreadID决定
比如两个线程同时调用JSockWork参数ThreadID分别是1和2,这样这里的ThreadID可能是1或2,1标示第一个线程2标示第二个线程
CliID是连接的编号,这个号码是0-79999的一个数字,已存在的连接不会有重复
IIP是客户端的ip地址,可以用函数inet_ntoa转换成字符串ip
Data是JSockSend发送的数据
Len是JSockSend发送的数据长度
}
// JSockDisconnect(ThreadID, CliID);
InterlockedIncrement(OnJSockSendCompleteCount);
end;
procedure pOnJSockDisconnect(ThreadID: Integer; CliID: Integer; IIP: Integer) stdcall;
begin
{当有客户端断开连接时触发该事件;
ThreadID线程序号,主要用户解决多线程共享资源访问问题,这个需要由JSockWork的ThreadID决定
比如两个线程同时调用JSockWork参数ThreadID分别是1和2,这样这里的ThreadID可能是1或2,1标示第一个线程2标示第二个线程
CliID是连接的编号,这个号码是0-79999的一个数字,已存在的连接不会有重复
IIP是客户端的ip地址,可以用函数inet_ntoa转换成字符串ip
}
InterlockedIncrement(OnJSockDisconnectCount);
end;
procedure pOnJSockError(ThreadID: Integer; CliID: Integer; IIP: Integer; ErrorType: Integer; ErrorCode: Integer) stdcall;
begin
{当有有错误或警告发生时触发该事件;
ThreadID线程序号,主要用户解决多线程共享资源访问问题,这个需要由JSockWork的ThreadID决定
比如两个线程同时调用JSockWork参数ThreadID分别是1和2,这样这里的ThreadID可能是1或2,1标示第一个线程2标示第二个线程
CliID是连接的编号,这个号码是0-79999的一个数字,已存在的连接不会有重复
IIP是客户端的ip地址,可以用函数inet_ntoa转换成字符串ip
ErrorType错误类型,大于0表示警告,小于等于0表示错误,警告对服务器或客户端继续运行是没有影响的,不用处理就行
ErrorCode错误编号,这里是标准的windows错误编号
}
//JSockDisconnect(ThreadID, CliID); 断开当前连接
if ErrorType > 0 then
begin
InterlockedIncrement(OnJSockErrorCount1);
end
else
begin
InterlockedIncrement(OnJSockErrorCount2);
end;
end;
var
strline: string;
host: string;
port: integer;
KeepAlive: integer;
SameIpCount: integer;
TickCountOld, TickCountNew: dword;
begin
writeln('请输入监听的IP地址:');
readln(strline);
host := strline;
writeln('请输入监听的端口:');
readln(strline);
port := strtoint(strline);
writeln('请输入测试连接的数据包多少秒发送一次:'); //0表示使用系统设置
readln(strline);
KeepAlive := strtoint(strline);
writeln('请输入同一IP最多允许多少个连接:'); //用于防攻击
readln(strline);
SameIpCount := strtoint(strline);
writeln('正在启动服务...');
if JSockStart(0, pchar(host), port, KeepAlive, SameIpCount, @pOnJSockConnect, @pOnJSockReceive, @pOnJSockSendComplete, @pOnJSockDisconnect, @pOnJSockError) > 0 then
begin
writeln('服务启动成功,等待客户端连接...');
TickCountOld := GetTickCount;
while true do
begin
JSockWork(1, 10); //查询事件,ThreadID线程序号,TimeOut没有事件时等待多少毫秒
TickCountNew := GetTickCount;
if TickCountNew - TickCountOld > 5000 then
begin
writeln('------------------------------------------------------');
writeln('当前连接数量:' + inttostr(OnJSockConnectCount-OnJSockDisconnectCount));
writeln('累计连接数量:' + inttostr(OnJSockConnectCount));
writeln('累计接收次数:' + inttostr(OnJSockReceiveCount));
writeln('累计发送次数:' + inttostr(OnJSockSendCount));
writeln('累计完成次数:' + inttostr(OnJSockSendCompleteCount));
writeln('累计断开次数:' + inttostr(OnJSockDisconnectCount));
writeln('累计警告次数:' + inttostr(OnJSockErrorCount1));
writeln('累计错误次数:' + inttostr(OnJSockErrorCount2));
writeln('------------------------------------------------------');
TickCountOld := TickCountNew;
end;
end;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -