Delphi最简化异步选择TCP服务器
网上Delphi的Socket服务器优良代码,实在少见,索性写个简化的异步Socket服务器,虽然代码较少,但却该有的都有了,使用的是异步选择WSAAsyncSelect,减少了编写线程的繁琐。可能会问,性能如何?当然使用窗体消息通知,占用的是主线程,侦听、发送、多个客户端的接收都一个线程,大量数据时,性能当然是差强人意的,编写这个代码目的也不在于此。但是在实际的项目中,大数据量的情况也不多,以下是代码:(Delphi7编译)
{
最简化的消息异步Socket 异步选择WSAAsyncSelect, 没有64的限制
}
program SocketDemo;
{$APPTYPE CONSOLE}
uses Windows, WinSock;
const
ListenPort : Word = ;
BufferSize : DWORD = ;
type
TConn = ^TConnData;
TConnData = record
FSocket: TSocket;
FAddrIn: TSockAddr;
Buffer : PChar;
BufLen : Integer;
end;
procedure DoSocketData(Conn: TConn);
var S: string;
begin
Writeln(Conn.Buffer);
//这里插入业务处理代码
S:= 'Server echo';
send(Conn.FSocket, PChar(S)^, Length(S), );
end;
//--------- 以下不要修改 -----------
const
wcName : PChar = 'THrWndClass';
WM_SOCKET = {WM_USER}$ + ; // 自定义消息
var
AddrInLen: Integer = SizeOf(TSockAddr);
var FConns: array of TConn;
function GetFreeConn: Integer;
var i: Integer;
begin
Result:= -;
for i:= to High(FConns) do
if FConns[i]=nil then begin
Result:= i; Break;
end;
if Result< then begin
Result:= Length(FConns); SetLength(FConns, Result+);
end;
FConns[Result]:= New(TConn);
GetMem(FConns[Result].Buffer, BufferSize+);
FConns[Result].BufLen:= BufferSize;
end;
function GetCltConn(S: TSocket): Integer;
var i: Integer;
begin
for i:= to High(FConns) do
if Assigned(FConns[i]) and (FConns[i].FSocket=S) then begin
Result:= i; Break;
end;
end;
procedure FreeConn(S: TSocket);
var id: Integer;
var Conn: TConn;
begin
id:= GetCltConn(S);
Conn:= FConns[id];
if not Assigned(Conn) then Exit;
FreeMem(Conn.Buffer);
CloseSocket(Conn.FSocket);
Dispose(Conn);
FConns[id]:= nil;
end;
function WndProc(wnd, msg, sock, wm: DWORD): Integer; stdcall;
var id, AddrLen: Integer;
begin
Result:= DefWindowProc(wnd, msg, sock, wm);
if (msg<>WM_SOCKET) or (wm=) then Exit;
case LoWord(wm) of
FD_ACCEPT:
begin
id:= GetFreeConn;
with FConns[id]^ do begin
FSocket:= Accept(sock, @FAddrIn, @AddrInLen);
WSAAsyncSelect(FSocket, wnd, WM_SOCKET, FD_READ or FD_CLOSE);
end;
end;
FD_READ:
begin
id:= GetCltConn(sock);
with FConns[id]^ do begin
BufLen:= Recv(sock, Buffer^, BufferSize, );
if (BufLen<) or (BufLen>Buflen) then FreeConn(sock) else
begin
Buffer[BufLen]:= #;
try DoSocketData(FConns[id]) except end;
end;
end;
end;
FD_CLOSE: FreeConn(sock);
end;
end;
function MakeWndHandle(WndProc: Pointer; wcName: PChar): HWND;
var wc: TWndClass;
begin
FillChar(wc, SizeOf(wc), );
wc.lpfnWndProc := WndProc;
wc.hInstance := HInstance;
wc.lpszClassName:= wcName;
Windows.RegisterClass(wc);
Result:= CreateWindow(wcName,'HrWnd',,,,,,,,HInstance,nil);
end;
function SrvListen(Port: Word): Boolean;
var Wnd: HWND; S: TSocket; Addr: TSockAddrIn; WSAData: TWSAData;
begin
WSAStartup($, WSAData);
Addr.sin_family := AF_INET;
Addr.sin_port := Swap(Port);
Addr.sin_addr.S_addr := ;
S:= Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
Bind(S, Addr, AddrInLen);
Wnd:= MakeWndHandle(@WndProc, wcName);
WSAAsyncSelect(S, Wnd, WM_SOCKET, FD_ACCEPT or FD_CLOSE);
//Writeln(SysErrorMessage(WSAGetLastError()), ' Wnd: ', Wnd);
Listen(S, );
end;
procedure SysFina;
begin
Windows.UnregisterClass(wcName, HInstance);
WSACleanup;
end;
procedure Stay;
var msg: TMsg;
begin
while GetMessage(msg, , , ) do begin
TranslateMessage(msg);
DispatchMessage (msg);
end;
PostQuitMessage();
end;
begin
//if InitProc <> nil then TProcedure(InitProc);
SrvListen(ListenPort);
Stay;
SysFina;
Halt();
end.
Delphi最简化异步选择TCP服务器的更多相关文章
- 网络IO模型-异步选择模型(Delphi版)
其实关于这个模型,网络上也有一个案例说明 老陈使用了微软公司的新式信箱.这种信箱非常先进,一旦信箱里有新的信件,盖茨就会给老陈打电话:喂,大爷,你有新的信件了!从此,老陈再也不必频繁上下楼检查信箱了, ...
- Swoole学习(七)Swoole之异步TCP服务器的创建
环境:Centos6.4,PHP环境:PHP7 <?php //创建TCP服务器 /** * $host 是swoole需要监听的ip,如果要监听本地,不对外服务,那么就是127.0.0.1;如 ...
- 【Python】使用socketserver建立一个异步TCP服务器
概述 这篇文章是讲解如何使用socketserver建立一个异步TCP服务器,其中Python版本为3.5.1. socketserver主要的类 socketserver模块中的类主要有以下几个:1 ...
- 06.swoole学习笔记--异步tcp服务器
<?php //创建tcp服务器 $host='0.0.0.0'; $port=; $serv=new swoole_server($host,$port); //设置异步进程工作数 $serv ...
- php的异步非阻塞swoole模块使用(一)实现简易tcp服务器--服务端
绑定tcp服务器的地址 $swserver = new swoole_server("127.0.0.1",9501); 设置tcp服务器装机容量(太危言耸听了-其实就是设置属性) ...
- 使用.net core在Ubuntu构建一个TCP服务器
介绍和背景 TCP编程是网络编程领域最有趣的部分之一.在Ubuntu环境中,我喜欢使用.NET Core进行TCP编程,并使用本机Ubuntu脚本与TCP服务器进行通信.以前,我在.NET框架本身写了 ...
- 使用CBrother做TCP服务器与C++客户端通信
使用CBrother脚本做TCP服务器与C++客户端通信 工作中总是会遇到一些对于服务器压力不是特别大,但是代码量比较多,用C++写起来很不方便.对于这种需求,我选择用CBrother脚本做服务器,之 ...
- LwIP应用开发笔记之五:LwIP无操作系统TCP服务器
前面我们实现了UDP服务器及客户端以及基于其上的TFTP应用服务器.接下来我们将实现同样广泛应用的TCP协议各类应用. 1.TCP简述 TCP(Transmission Control Protoco ...
- PHP写的异步高并发服务器,基于libevent
PHP写的异步高并发服务器,基于libevent 博客分类: PHP PHPFPSocketLinuxQQ 本文章于2013年11月修改. swoole已使用C重写作为PHP扩展来运行.项目地址:h ...
随机推荐
- 小程序-文章:微信小程序常见的UI框架/组件库总结
ylbtech-小程序-文章:微信小程序常见的UI框架/组件库总结 1.返回顶部 1. 想要开发出一套高质量的小程序,运用框架,组件库是省时省力省心必不可少一部分,随着小程序日渐火爆,各种不同类型的小 ...
- ubuntu搭建开发环境踩坑实录
谨以此文,记录和ubuntu系统不死不休的搏斗过程,后续待补. 1.双系统安装,windows采用uefi模式安装(优启通可制作uefi的win10安装盘),ubuntu不要划分boot区,而应该划分 ...
- 【181】IDL 代码从 Windows 转移到 Linux
文件夹分隔符,Windows 是“/”,Linux 是“\”,按照程序,需要修改 通过 bash 运行 *.pro 文件,貌似只能运行没有参数的,有参数的需要写入到文件中 idl 的文件不能用大写字母 ...
- bzoj 1609[Usaco2008 Feb]Eating Together麻烦的聚餐【dp】
设up[i][j]为第i位升序为j的最小修改数,down为降序 #include<iostream> #include<stdio.h> using namespace std ...
- Luogu P1119 灾后重建 【floyd】By cellur925
题目传送门 这道题我们很容易想到对于每次询问,都跑一遍最短路(spfa,虽然他已经死了).只需在松弛的时候加入当前相关的点是否已经修好的判断,果不其然的TLE了4个点. (然鹅我第一次用spfa跑的时 ...
- hdu 2063 过山车 (最大匹配 匈牙利算法模板)
匈牙利算法是由匈牙利数学家Edmonds于1965年提出,因而得名.匈牙利算法是基于Hall定理中充分性证明的思想,它是部图匹配最常见的算法,该算法的核心就是寻找增广路径,它是一种用增广路径求二分图最 ...
- Windows软件推荐
本篇博文主要记录一些实用性的windows软件或者插件,重在积累! 工具类 1.截图软件 https://zh.snipaste.com/ Snipaste 是一个简单但强大的截图工具,也可以让你将截 ...
- MyEclipse配置Tomcat
1.在Window->Perferences->MyEclipse->Servers->Tomcat->Tomcat 7.x中启用Tomcat并配置Tomcat路径和JD ...
- poj1781In Danger(约瑟夫) 问题
链接 之前队内赛中的一道题目 当时怎么想也没想到,就一直放到了今天,刚才看另一题的讲解突然看到时拿这个题作为引子来讲的,就仔细看了下. 参考<<具体数学>> p7. Josep ...
- h5学习-webstorm工具的激活
这里有个快速激活webstorm的方法:http://jingyan.baidu.com/article/9f63fb919674f2c8400f0e9a.html h5的轮廓工具:https://g ...