TCP转发服务器的例子


2009-05-28 15:02:14|  分类: 电脑知识|字号 订阅

这几种机器用事件模型应该够用了。 
下面是一个TCP转发服务器的例子,他的作用是有一些客户端连到服务器后,任何一个客户端发给服务器的数据都被服务器原封不动的转发到所有客户端,类似于多人聊天的概念。 
program EventSelectServer; 
{$APPTYPE CONSOLE} 
uses 
SysUtils, WinSock2; 
const 
Port = 5150; 
MaxConnection = 63; 
BufSize = 1024; 
var 
wsaData: TWSAData; 
Connection: array [0..MaxConnection] of TSocket; 
Events: array [0..MaxConnection] of WSAEvent; 
ConnectionNum: Integer; 
Index: Integer; 
i, j: Integer; 
NetworkEvent: TWSANetworkEvents; 
ServerAddr: TSockAddrIn; 
ClientAddr: TSockAddrIn; 
ClientAddrLen: Integer; 
Buf: string; 
Ret: Integer; 
begin 
Ret:=WSAStartup($202, wsaData); 
if Ret<>0 then 
begin 
   WriteLn('WSAStartup failed with error ', Ret); 
   ReadLn; 
   Exit 
end; 
ConnectionNum:=1; 
Connection[0]:=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
if Connection[0]=INVALID_SOCKET then 
begin 
   WriteLn('socket failed with error ', WSAGetLastError); 
   ReadLn; 
   Exit 
end; 
ServerAddr.sin_family:=AF_INET; 
ServerAddr.sin_port:=htons(Port); 
ServerAddr.sin_addr.S_addr:=htonl(INADDR_ANY); 
if bind(Connection[0], @ServerAddr, SizeOf(ServerAddr))=SOCKET_ERROR then 
begin 
   WriteLn('bind failed with error ', WSAGetLastError); 
   ReadLn; 
   Exit 
end; 
Events[0]:=WSACreateEvent; 
if Events[0]=WSA_INVALID_EVENT then 
begin 
   WriteLn('WSACreateEvent failed with error ', WSAGetLastError); 
   ReadLn; 
   Exit 
end; 
if WSAEventSelect(Connection[0], Events[0], FD_ACCEPT)=SOCKET_ERROR then 
begin 
   WriteLn('WSAEventSelect failed with error ', WSAGetLastError); 
   ReadLn; 
   Exit 
end; 
if listen(Connection[0], 5)=SOCKET_ERROR then 
begin 
   WriteLn('listen failed with error ', WSAGetLastError); 
   ReadLn; 
   Exit 
end; 
while True do 
begin 
   Ret:=WSAWaitForMultipleEvents(ConnectionNum, @Events[0], False, WSA_INFINITE, False); 
   Index:=Ret-WSA_WAIT_EVENT_0; 
   for i:=Index to ConnectionNum-1 do 
   begin 
     Ret:=WSAWaitForMultipleEvents(1, @Events , True, 0, False); 
     if (Ret=WSA_WAIT_FAILED) or (Ret=WSA_WAIT_TIMEOUT) then 
       Continue; 
     if WSAEnumNetworkEvents(Connection, Events, @NetworkEvent)=SOCKET_ERROR then 
       Continue; 
     if (NetworkEvent.lNetworkEvents and FD_ACCEPT)<>0 then 
     begin 
       if NetworkEvent.iErrorCode[FD_ACCEPT_BIT]<>0 then 
       begin 
         WriteLn('FD_ACCEPT failed with error ', NetworkEvent.iErrorCode[FD_ACCEPT_BIT]); 
         Continue 
       end; 
       if ConnectionNum<=MaxConnection then 
       begin 
         ClientAddrLen:=SizeOf(ClientAddr); 
         Connection[ConnectionNum]:=accept(Connection, ClientAddr, ClientAddrLen); 
         if Connection[ConnectionNum]=INVALID_SOCKET then 
         begin 
           WriteLn('accept failed with error ', WSAGetLastError); 
           Continue 
         end; 
         Events[ConnectionNum]:=WSACreateEvent; 
         if Events[ConnectionNum]=WSA_INVALID_EVENT then 
         begin 
           WriteLn('WSACreateEvent failed with error ', WSAGetLastError); 
           if closesocket(Connection[ConnectionNum])=SOCKET_ERROR then 
             WriteLn('closesocket failed with error ', WSAGetLastError); 
           Continue 
         end; 
         if WSAEventSelect(Connection[ConnectionNum], Events[ConnectionNum], FD_READ or FD_CLOSE)=SOCKET_ERROR then 
         begin 
           WriteLn('WSAEventSelect failed with error ', WSAGetLastError); 
           if closesocket(Connection[ConnectionNum])=SOCKET_ERROR then 
             WriteLn('closesocket failed with error ', WSAGetLastError); 
           if not WSACloseEvent(Events[ConnectionNum]) then 
             WriteLn('WSACloseEvent failed with error ', WSAGetLastError); 
           Continue 
         end; 
         WriteLn('accetp ', inet_ntoa(ClientAddr.sin_addr), ':', ntohs(ClientAddr.sin_port)); 
         Inc(ConnectionNum) 
       end 
     end; 
     if (NetworkEvent.lNetworkEvents and FD_READ)<>0 then 
     begin 
       if NetworkEvent.iErrorCode[FD_READ_BIT]<>0 then 
       begin 
         WriteLn('FD_READ failed with error ', NetworkEvent.iErrorCode[FD_READ_BIT]); 
         Continue 
       end; 
       SetLength(Buf, BufSize); 
       Ret:=recv(Connection, Buf[1], BufSize, 0); 
       if Ret=SOCKET_ERROR then 
       begin 
         WriteLn('recv failed with error ', WSAGetLastError); 
         Continue 
       end; 
       SetLength(Buf, Ret); 
       ClientAddrLen:=SizeOf(ClientAddr); 
       if getpeername(Connection, ClientAddr, ClientAddrLen)=SOCKET_ERROR then 
       begin 
         WriteLn('getpeername failed with error ', WSAGetLastError); 
         Continue 
       end; 
       Buf:='来自'+inet_ntoa(ClientAddr.sin_addr)+':'+IntToStr(ntohs(ClientAddr.sin_port))+' '+Buf; 
       Buf:=TimeToStr(Time)+' '+Buf; 
       for j:=1 to ConnectionNum do 
         if send(Connection[j], Buf[1], Length(Buf), 0)=SOCKET_ERROR then 
         begin 
           WriteLn('send failed with error ', WSAGetLastError); 
           Continue 
         end; 
       WriteLn(Buf) 
     end; 
     if (NetworkEvent.lNetworkEvents and FD_CLOSE)<>0 then 
     begin 
       if NetworkEvent.iErrorCode[FD_CLOSE_BIT]<>0 then 
       begin 
         WriteLn('FD_CLOSE failed with error ', NetworkEvent.iErrorCode[FD_CLOSE_BIT]); 
         Continue 
       end; 
       ClientAddrLen:=SizeOf(ClientAddr); 
       if getpeername(Connection, ClientAddr, ClientAddrLen)=SOCKET_ERROR then 
       begin 
         WriteLn('getpeername failed with error ', WSAGetLastError); 
         Continue 
       end; 
       Buf:='closesocket '+inet_ntoa(ClientAddr.sin_addr)+':'+IntToStr(ntohs(ClientAddr.sin_port)); 
       WriteLn(Buf); 
       if closesocket(Connection)=SOCKET_ERROR then 
         WriteLn('closesocket failed with error ', WSAGetLastError); 
       if not WSACloseEvent(Events) then 
         WriteLn('WSACloseEvent failed with error ', WSAGetLastError); 
       if ConnectionNum>1 then 
       begin 
         Connection:=Connection[ConnectionNum-1]; 
         Events:=Events[ConnectionNum-1]; 
         Dec(ConnectionNum) 
       end 
     end 
   end 
end; 
for i:=0 to ConnectionNum do 
   if closesocket(Connection)=SOCKET_ERROR then 
   begin 
     WriteLn('closesocket failed with error ', WSAGetLastError); 
     ReadLn; 
     Exit 
   end; 
if WSACleanup=SOCKET_ERROR then 
begin 
   WriteLn('WSCleanup failed with error ', WSAGetLastError); 
   ReadLn; 
   Exit 
end 
end.  

你可能感兴趣的:(TCP转发服务器的例子)