TCP转发服务器的例子

34 篇文章 1 订阅
19 篇文章 0 订阅

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.  
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值