程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> Delphi最簡化異步選擇TCP服務器,delphitcp

Delphi最簡化異步選擇TCP服務器,delphitcp

編輯:Delphi

Delphi最簡化異步選擇TCP服務器,delphitcp


    網上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.

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved