网上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服务器的更多相关文章

  1. 网络IO模型-异步选择模型(Delphi版)

    其实关于这个模型,网络上也有一个案例说明 老陈使用了微软公司的新式信箱.这种信箱非常先进,一旦信箱里有新的信件,盖茨就会给老陈打电话:喂,大爷,你有新的信件了!从此,老陈再也不必频繁上下楼检查信箱了, ...

  2. Swoole学习(七)Swoole之异步TCP服务器的创建

    环境:Centos6.4,PHP环境:PHP7 <?php //创建TCP服务器 /** * $host 是swoole需要监听的ip,如果要监听本地,不对外服务,那么就是127.0.0.1;如 ...

  3. 【Python】使用socketserver建立一个异步TCP服务器

    概述 这篇文章是讲解如何使用socketserver建立一个异步TCP服务器,其中Python版本为3.5.1. socketserver主要的类 socketserver模块中的类主要有以下几个:1 ...

  4. 06.swoole学习笔记--异步tcp服务器

    <?php //创建tcp服务器 $host='0.0.0.0'; $port=; $serv=new swoole_server($host,$port); //设置异步进程工作数 $serv ...

  5. php的异步非阻塞swoole模块使用(一)实现简易tcp服务器--服务端

    绑定tcp服务器的地址 $swserver = new swoole_server("127.0.0.1",9501); 设置tcp服务器装机容量(太危言耸听了-其实就是设置属性) ...

  6. 使用.net core在Ubuntu构建一个TCP服务器

    介绍和背景 TCP编程是网络编程领域最有趣的部分之一.在Ubuntu环境中,我喜欢使用.NET Core进行TCP编程,并使用本机Ubuntu脚本与TCP服务器进行通信.以前,我在.NET框架本身写了 ...

  7. 使用CBrother做TCP服务器与C++客户端通信

    使用CBrother脚本做TCP服务器与C++客户端通信 工作中总是会遇到一些对于服务器压力不是特别大,但是代码量比较多,用C++写起来很不方便.对于这种需求,我选择用CBrother脚本做服务器,之 ...

  8. LwIP应用开发笔记之五:LwIP无操作系统TCP服务器

    前面我们实现了UDP服务器及客户端以及基于其上的TFTP应用服务器.接下来我们将实现同样广泛应用的TCP协议各类应用. 1.TCP简述 TCP(Transmission Control Protoco ...

  9. PHP写的异步高并发服务器,基于libevent

    PHP写的异步高并发服务器,基于libevent 博客分类: PHP PHPFPSocketLinuxQQ  本文章于2013年11月修改. swoole已使用C重写作为PHP扩展来运行.项目地址:h ...

随机推荐

  1. 【转】iOS笔记-自定义控件(OC)

    原文网址:http://www.jianshu.com/p/f23862eb7b8a 导读: iOS开发中,很多时候系统提供的控件并不能很好的满足我们的需求,因此,自定义控件便成为搭建UI界面中必不可 ...

  2. HDU1180:诡异的楼梯

    传送门 题意 迷宫搜索 分析 这题写起来挺简单的,锻炼搜索基本功,一开始用记忆化搜索TLE了,改用访问标记,0ms过了,用优先队列保证终点最快达到,我会在代码中提供一些强力数据 trick 1.遇到梯 ...

  3. bzoj 1040: [ZJOI2008]骑士【基环树+树形dp】

    没考虑可以连着两个不选--直接染色了 实际上是基环森林,对于每棵基环树,dfs找出一个环边,然后断掉这条边,分别对这条边的两端点做一边treedp,取max加进答案里 treedp是设f[u]为选u点 ...

  4. css实现侧边展开收起

    前言:因为突然想研究研究侧边栏滑动展开收起怎么做的,就去baidu了一下transition. 详情 内容1 内容1 内容1 内容1 内容1 右侧有实现demo.就是那个绿色的详情 先来看一下我的代码 ...

  5. iOS 消除Xcode警告

    - undeclared selector #pragma clang diagnostic push #pragma clang diagnostic ignored"-Wundeclar ...

  6. linux 磁盘 分区、格式化、挂载

    将容量结果易读的容量格式显示出来df -h 分区 初次接触仅分成两个分区(“/与Swap”)预留一个备用的剩余磁盘容量 磁盘分区 fdisk #df /找出磁盘文件名#fdisk /dev/hdc#m ...

  7. javascript监听值变化

    最近面了有道前端实习,人品爆发一面过了.但是在一面中面试官问了一个问题”MVC用javascript如何实现?如果实现双向绑定?值变化监听?“ 当时我回答”js好像没函数进行值变化监听“ 后来想想很不 ...

  8. _bzoj2243 [SDOI2011]染色【树链剖分】

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2243 裸的树链剖分,最开始我保存一个线段树节点的color值时(若有多种颜色则为-1),不小 ...

  9. JetSpeed2部署至Apusic操作步骤记录

    JetSpeed2部署至Apusic操作步骤记录. 1.创建Apusic新域,配置端口.管理端口和管理密码. 2.将Tomcat/lib目录中的所有jar包复制至Apusic域中的lib目录中(包括数 ...

  10. http缓存之lastModified和etag

    1.cache-control 访问资源 首次访问页面时间:2018.2.1  9:56  (当前时间=GMT时间+8h) 缓存时长max-age:1 day Expire缓存失效时间:2018.2. ...