TCP轉發伺服器的例子

晴天_娃娃發表於2012-12-06

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.  

相關文章