Delphi最简化异步选择TCP服务器

网上Delphi的Socket服务器优良代码,实在少见,索性写个简化的异步Socket服务器,虽然代码较少,但却该有的都有了,使用的是异步选择WSAAsyncSelect,减少了编写线程的繁琐。可能会问,性能如何?当然使用窗体消息通知,占用的是主线程,侦听、发送、多个客户端的接收都一个线程,大量数据时,性能当然是差强人意的,编写这个代码目的也不在于此。但是在实际的项目中,大数据量的情况也不多,以下是代码:(Delphi7编译)

  1 {
  2    最简化的消息异步Socket 异步选择WSAAsyncSelect, 没有64的限制
  3 }
  4
  5 program SocketDemo;
  6
  7 {$APPTYPE CONSOLE}
  8
  9 uses Windows, WinSock;
 10
 11 const
 12   ListenPort : Word  = 12345;
 13   BufferSize : DWORD = 1024;
 14
 15 type
 16   TConn = ^TConnData;
 17   TConnData = record
 18     FSocket: TSocket;
 19     FAddrIn: TSockAddr;
 20     Buffer : PChar;
 21     BufLen : Integer;
 22   end;
 23
 24 procedure DoSocketData(Conn: TConn);
 25 var S: string;
 26 begin
 27   Writeln(Conn.Buffer);
 28   //这里插入业务处理代码
 29   S:= ‘Server echo‘;
 30   send(Conn.FSocket, PChar(S)^, Length(S), 0);
 31 end;
 32
 33
 34
 35 //--------- 以下不要修改 -----------
 36 const
 37   wcName : PChar = ‘THrWndClass‘;
 38   WM_SOCKET = {WM_USER}$0400 + 101;        // 自定义消息
 39
 40 var
 41   AddrInLen: Integer = SizeOf(TSockAddr);
 42
 43 var FConns: array of TConn;
 44
 45 function GetFreeConn: Integer;
 46 var i: Integer;
 47 begin
 48   Result:= -1;
 49   for i:=0 to High(FConns) do
 50   if FConns[i]=nil then begin
 51     Result:= i; Break;
 52   end;
 53   if Result<0 then begin
 54     Result:= Length(FConns); SetLength(FConns, Result+1);
 55   end;
 56   FConns[Result]:= New(TConn);
 57   GetMem(FConns[Result].Buffer, BufferSize+1);
 58   FConns[Result].BufLen:= BufferSize;
 59 end;
 60
 61 function GetCltConn(S: TSocket): Integer;
 62 var i: Integer;
 63 begin
 64   for i:=0 to High(FConns) do
 65   if Assigned(FConns[i]) and (FConns[i].FSocket=S) then begin
 66     Result:= i;  Break;
 67   end;
 68 end;
 69
 70 procedure FreeConn(S: TSocket);
 71 var id: Integer;
 72 var Conn: TConn;
 73 begin
 74   id:= GetCltConn(S);
 75   Conn:= FConns[id];
 76   if not Assigned(Conn) then Exit;
 77   FreeMem(Conn.Buffer);
 78   CloseSocket(Conn.FSocket);
 79   Dispose(Conn);
 80   FConns[id]:= nil;
 81 end;
 82
 83 function WndProc(wnd, msg, sock, wm: DWORD): Integer; stdcall;
 84 var id, AddrLen: Integer;
 85 begin
 86   Result:= DefWindowProc(wnd, msg, sock, wm);
 87   if (msg<>WM_SOCKET) or (wm=0) then Exit;
 88   case LoWord(wm) of
 89     FD_ACCEPT:
 90       begin
 91         id:= GetFreeConn;
 92         with FConns[id]^ do begin
 93           FSocket:= Accept(sock, @FAddrIn, @AddrInLen);
 94           WSAAsyncSelect(FSocket, wnd, WM_SOCKET, FD_READ or FD_CLOSE);
 95         end;
 96       end;
 97     FD_READ:
 98       begin
 99         id:= GetCltConn(sock);
100         with FConns[id]^ do begin
101           BufLen:= Recv(sock, Buffer^, BufferSize, 0);
102           if (BufLen<0) or (BufLen>Buflen) then FreeConn(sock) else
103           begin
104             Buffer[BufLen]:= #0;
105             try DoSocketData(FConns[id]) except end;
106           end;
107         end;
108       end;
109     FD_CLOSE: FreeConn(sock);
110   end;
111 end;
112
113 function MakeWndHandle(WndProc: Pointer; wcName: PChar): HWND;
114 var wc: TWndClass;
115 begin
116   FillChar(wc, SizeOf(wc), 0);
117   wc.lpfnWndProc  := WndProc;
118   wc.hInstance    := HInstance;
119   wc.lpszClassName:= wcName;
120   Windows.RegisterClass(wc);
121   Result:= CreateWindow(wcName,‘HrWnd‘,0,0,0,0,0,0,0,HInstance,nil);
122 end;
123
124 function SrvListen(Port: Word): Boolean;
125 var Wnd: HWND; S: TSocket; Addr: TSockAddrIn; WSAData: TWSAData;
126 begin
127   WSAStartup($0202, WSAData);
128   Addr.sin_family      := AF_INET;
129   Addr.sin_port        := Swap(Port);
130   Addr.sin_addr.S_addr := 0;
131   S:= Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
132   Bind(S, Addr, AddrInLen);
133
134   Wnd:= MakeWndHandle(@WndProc, wcName);
135   WSAAsyncSelect(S, Wnd, WM_SOCKET, FD_ACCEPT or FD_CLOSE);
136   //Writeln(SysErrorMessage(WSAGetLastError()), ‘ Wnd: ‘, Wnd);
137   Listen(S, 5);
138 end;
139
140 procedure SysFina;
141 begin
142   Windows.UnregisterClass(wcName, HInstance);
143   WSACleanup;
144 end;
145
146 procedure Stay;
147 var msg: TMsg;
148 begin
149   while GetMessage(msg, 0, 0, 0) do begin
150     TranslateMessage(msg);
151     DispatchMessage (msg);
152   end;
153   PostQuitMessage(0);
154 end;
155
156 begin
157   //if InitProc <> nil then TProcedure(InitProc);
158   SrvListen(ListenPort);
159   Stay;
160   SysFina;
161   Halt(0);
162 end.
时间: 2024-10-21 12:36:54

Delphi最简化异步选择TCP服务器的相关文章

c#异步Socket Tcp服务器实现

原创性申明 本文作者: 小竹zz  本文地址:http://blog.csdn.net/zhujunxxxxx 转载请注明出处. 介绍 我之前写过一篇IOCP的文章: http://blog.csdn.net/zhujunxxxxx/article/details/43573879 这个比异步socket性能好,因为它复用对象了. 在c#中微软已经提供了TcpListener和TcpClient来实现Tcp的通讯,这部分已经有人写了比较好的异步服务器代码 http://www.cnblogs.c

C#网络编程系列文章(三)之TcpListener实现异步TCP服务器

原创性声明 本文作者:小竹zz 本文地址http://blog.csdn.net/zhujunxxxxx/article/details/44258719 转载请注明出处 本文介绍 TcpListener 类提供一些简单方法,用于在阻止同步模式下侦听和接受传入连接请求. 可使用 TcpClient 或 Socket 来连接 TcpListener. 可使用 IPEndPoint.本地 IP 地址及端口号或者仅使用端口号,来创建 TcpListener. 可以将本地 IP 地址指定为 Any,将本

Boost Asio 异步TCP服务器框架

Boost Asio 异步TCP服务器框架 flyfish 2015-5-30 session 类 头文件 #pragma once #include <boost/asio.hpp> #include <boost/bind.hpp> #include <boost/shared_ptr.hpp> #include <boost/enable_shared_from_this.hpp> class session: public boost::enable

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

<?php //创建tcp服务器 $host='0.0.0.0'; $port=9501; $serv=new swoole_server($host,$port); //设置异步进程工作数 $serv->set(array('task_worker_num'=>4)); //投递异步任务 $serv->on('receive',function($serv,$fd,$from_id,$data){ $task_id=$serv->task($data); echo &quo

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

绑定tcp服务器的地址 $swserver = new swoole_server("127.0.0.1",9501); 设置tcp服务器装机容量(太危言耸听了-其实就是设置属性) $swserver->set([ 'worker_num'=>8, 'max_request'=>10000 ]); 读取连接请求信息---接通 $swserver->on('connect',function($swserver,$fd,$reactor_id){ echo &qu

使用OTP原理构建一个非阻塞的TCP服务器(转)

经测试可用! 原文地址:http://www.iucai.com/?paged=8 Erlang OTP设计原理已经被shiningray兄翻译透了.请参见.http://erlang.shiningray.cn/otp-design-principles/index.html 这里翻译了一篇余锋老大和lzy.je老大推荐的文章,闲话不说,奉上. 使用OTP原理构建一个非阻塞的TCP服务器 原文网址:(打不开的同学请自觉FQ) http://www.trapexit.org.nyud.net:8

C#网络编程系列文章(四)之TcpListener实现同步TCP服务器

原创性声明 本文作者:小竹zz 本文地址http://blog.csdn.net/zhujunxxxxx/article/details/44258719 转载请注明出处 本文介绍 TcpListener 类提供一些简单方法,用于在阻止同步模式下侦听和接受传入连接请求. 可使用 TcpClient 或 Socket 来连接 TcpListener. 可使用 IPEndPoint.本地 IP 地址及端口号或者仅使用端口号,来创建 TcpListener. 可以将本地 IP 地址指定为 Any,将本

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

介绍和背景 TCP编程是网络编程领域最有趣的部分之一.在Ubuntu环境中,我喜欢使用.NET Core进行TCP编程,并使用本机Ubuntu脚本与TCP服务器进行通信.以前,我在.NET框架本身写了一篇关于TCP服务器和客户端的文章.现在,.NET框架本身将是开源的.我想写一些关于他们之间的沟通渠道.基本上,我只是测试在新的.NET环境下工作的情况,而不是在旧的.NET框架环境中工作. 然而,在这篇文章中,我有一大堆的额外功能可供你使用.我将向您展示您将使用的方法来构建自己的TCP服务器,使用

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

使用CBrother脚本做TCP服务器与C++客户端通信 工作中总是会遇到一些对于服务器压力不是特别大,但是代码量比较多,用C++写起来很不方便.对于这种需求,我选择用CBrother脚本做服务器,之所以不选择Python是因为python的语法我实在是适应不了,再来CBrother的网络框架也是用C++封装的异步IO,性能还是很有保证的. 废话不多说,先来看下服务器代码,我这里只是记录一个例子,不是全部代码,方便后面做项目的时候直接来自己博客复制代码修改. 1 import CBSocket.