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 ...
随机推荐
- 【Bitset】 BZOJ4810
难得学习一下C++的库..[至今连map,vector都没用过的我.. 首先#include<bitset>或<bits/stdc++.h> 定义函数: { bitset & ...
- javascript 反斜杠\
通常,我们在动态给定一个div的innerHTML时,通常是样做的: <div id="demo1" /> <SCRIPT> var demo= docum ...
- 异常处理:Cannot attach the file as database 'membership'.
Cannot attach the file 'D:\GitHome\cae\CAE\App_Data\membership.mdf' as database 'membership'. 说明: 执行 ...
- Thinkpad x230i安装Ubuntu10.04发生no network devices available
这个是由于10.04版本没有集成x230i的网卡驱动导致,需要到http://sourceforge.net/projects/e1000/f ... %20stable/下载最新版本驱动,并安装,之 ...
- P4170 [CQOI2007]涂色
传送门 区间dp,设\(f[l][r]\)表示区间\((l,r)\)的最小次数,当\(l==r\)时为\(1\),当\(s[l]==s[r]\)时为\(min(f[l][r-1],f[l+1][r]) ...
- Golang bash alias 自动配置GOPATH并运行项目
BASH代码: source ~/.bash_profile; export GOPATH=$GOPATH:`cd ..; pwd`; echo -e "* GOPATH: $GOPATH ...
- c语言程序设计案例教程(第2版)笔记(六)—字符串处理实例
字符串处理 功能描述:从键盘输入一个文本行后,为用户提供菜单选择,实现字符串一些操作——显示文本行.查找并替换指定子串.删除指定子串.统计指定子串数目. 实现代码: #include<stdio ...
- Dexposed:android免Root无侵入Aop框架
在网上看到了阿里推出的一个android开源项目,名为Dexposed, 是一个Android平台下的无侵入运行期AOP框架.旨在解决像性能监控.在线热补丁等移动开发常见难题,典型使用场景为: AOP ...
- [Usaco2003 Open]Lost Cows
Description N (2 <= N <= 8,000) cows have unique brands in the range 1..N. In a spectacular di ...
- LightOj 1074 Extended Traffic (spfa+负权环)
题目链接: http://lightoj.com/volume_showproblem.php?problem=1074 题目大意: 有一个大城市有n个十字交叉口,有m条路,城市十分拥挤,因此每一个路 ...