From ab086a8e20ceb5bd8ef31875c9fb962a2abb7d9f Mon Sep 17 00:00:00 2001 From: marco Date: Mon, 5 Jun 2000 07:19:32 +0000 Subject: [PATCH] * added setsocketoptions + pulled it through source beautifier --- docs/sockex/serverex.pp | 345 +++++++++++++++++++++------------------- 1 file changed, 181 insertions(+), 164 deletions(-) diff --git a/docs/sockex/serverex.pp b/docs/sockex/serverex.pp index 3e16d525c0..aad4fdaf83 100644 --- a/docs/sockex/serverex.pp +++ b/docs/sockex/serverex.pp @@ -9,14 +9,14 @@ Program Socket_Comms_Test; to the port number. This program runs as-is, just telnet localhost 5000 to connect to it. No warranty at all, I will not be responsible if this sets fire to your dog! - + This is exactly as I use it, I have just put the references to my db unit in curly brackets. It just echoes back what you type on a line by line basis Run it in X or on a seperate virtual console to the one you are telneting from as it prints a LOT of info to the console about what it is doing and such. I'm not a pretty coder at all, so please, no complaints about the lack of comments or coding style, unless they are very contructive ;p) - + type 'quit', minus the quotes and in lower case on the console to exit the program. The only problem I can see with this, is if you exit it, it does not shut down the connections to the telnet sessions cleanly, and therefore @@ -26,256 +26,273 @@ Program Socket_Comms_Test; If you know how to fix this, please let me know and I'll update the code. If you exit all your telnet sessions before shutting the server down, it works fine. - + Hope some of you find this usefull. I wrote it, purely because there is a big lack of examples of linux port use in FPC. And I know NO C, therefore the examples on the net meant nothing to me. - + All I ask is :- If you like it, use it or want to change it, please drop me an E-mail. - + Regards Brad Campbell bcampbel@omen.net.au ***************************************************************************} - + +{$mode ObjFPC} + Uses Linux, Sockets, Sysutils{, dbu}; Const - NumberofConnections = 5; - -Type ConnectionType = Record - IP : Cardinal; - Port : Word; - Handle : Integer; - Connected : Boolean; - IdleTimer : Integer; - End; - + NumberofConnections = 5; + +Type ConnectionType = Record + IP : Cardinal; + Port : Word; + Handle : Integer; + Connected : Boolean; + IdleTimer : Integer; + End; + Var - Connection : Array[1..NumberofConnections] of ConnectionType; - FDS : FDSet; - S : LongInt; - PortNumber : Word; - GreatestHandle : Integer; - Quit : Boolean; - Command : String; - + Connection : Array[1..NumberofConnections] Of ConnectionType; + FDS : FDSet; + S : LongInt; + PortNumber : Word; + GreatestHandle : Integer; + Quit : Boolean; + Command : String; + Procedure ZeroConnection; + Var Loop : Integer; Begin -For Loop := 1 to NumberOfConnections do -Connection[Loop].Connected := False; + For Loop := 1 To NumberOfConnections Do + Connection[Loop].Connected := False; End; Function FreeConnections : Integer; -Var Loop : Integer; - Result : Integer; + +Var Loop : Integer; + Begin -Result := 0; -For Loop := 1 to NumberOfConnections do -If Not Connection[Loop].Connected then Result := Result + 1; -FreeConnections := Result; + Result := 0; + For Loop := 1 To NumberOfConnections Do + If Not Connection[Loop].Connected Then Inc(Result); + FreeConnections := Result; End; Function GetFreeConnection : Integer; + Var Loop : Integer; - Result : Integer; - Found : Boolean; + Found : Boolean; Begin -Result := 0; -Loop := 1; -Found := False; -While (Loop < NumberOfConnections + 1) and (Not Found) do -Begin - If Not Connection[Loop].Connected then - Begin - Found := True; - Result := Loop; - End; - Loop := Loop + 1; -GetFreeConnection := Result; -End; + Result := 0; + Loop := 1; + Found := False; + While (Loop < NumberOfConnections + 1) and (Not Found) Do + Begin + If Not Connection[Loop].Connected Then + Begin + Found := True; + Result := Loop; + End; + Inc(Loop); + GetFreeConnection := Result; + End; End; Procedure PError(S : String); Begin - Writeln(S,SocketError); - Halt(100); + Writeln(S,SocketError); + Halt(100); End; Procedure PDebug(S : String); Begin - Writeln(S); + Writeln(S); End; Procedure PDebugNOLF(S: String); Begin - Write(S); + Write(S); End; - + Function SockAddrtoString(InAddr : LongWord) : String; Var - P1,P2,P3,P4 : Byte; - S1,S2,S3,S4 : String; + P1,P2,P3,P4 : Byte; + S1,S2,S3,S4 : String; Begin - P1 := (InAddr And $ff000000) Shr 24; - P2 := (InAddr And $ff0000) Shr 16; - P3 := (InAddr And $ff00) Shr 8; - P4 := InAddr And $FF; - Str(P1,S1); - Str(P2,S2); - Str(P3,S3); - Str(P4,S4); - SockAddrtoString := S4+'.'+S3+'.'+S2+'.'+S1; + P1 := (InAddr And $ff000000) Shr 24; + P2 := (InAddr And $ff0000) Shr 16; + P3 := (InAddr And $ff00) Shr 8; + P4 := InAddr And $FF; + Str(P1,S1); + Str(P2,S2); + Str(P3,S3); + Str(P4,S4); + SockAddrtoString := S4+'.'+S3+'.'+S2+'.'+S1; End; Procedure WelcomeHandle(Handle, ConnNum : Integer); -Var Buffer : String; - Sent : Integer; + +Var Buffer : String; + Sent : Integer; Begin -Buffer := 'Welcome to Brads Server 1.0'+#10+#13+'You Are Connection '+ -InttoStr(ConnNum)+' Of '+InttoStr(NumberofConnections)+ -', With '+InttoStr(FreeConnections)+' Connections Free'#13+#10; -Sent := Send(Handle,Buffer[1],Length(Buffer),0); -If Sent <> Length(Buffer) then PDebug('Wanted to Send : ' -+InttoStr(Length(Buffer))+' Sent Only : '+InttoStr(Sent)+ -' to Connection : '+InttoStr(ConnNum)); + Buffer := 'Welcome to Brads Server 1.0'+#10+#13+'You Are Connection '+ + InttoStr(ConnNum)+' Of '+InttoStr(NumberofConnections)+ + ', With '+InttoStr(FreeConnections)+' Connections Free'#13+#10; + Sent := Send(Handle,Buffer[1],Length(Buffer),0); + If Sent <> Length(Buffer) Then + PDebug('Wanted to Send : ' +InttoStr(Length(Buffer))+' Sent Only : ' + +InttoStr(Sent)+' to Connection : '+InttoStr(ConnNum)); End; Procedure AcceptNewConnection; + Var ConnectionNumber : Integer; - Handle : LongInt; - FromAddrSize : LongInt; - FromAddr : TInetSockAddr; + Handle : LongInt; + FromAddrSize : LongInt; + FromAddr : TInetSockAddr; Begin -FromAddrSize := Sizeof(FromAddr); -If FreeConnections > 0 then Begin -ConnectionNumber := GetFreeConnection; -PDebug('Accepting New Connection Number : '+InttoStr(ConnectionNumber)); -Handle := Accept(S,FromAddr,FromAddrSize); -If Handle < 0 then PError('Accept Error!!'); -PDebug('Accepted From : '+SockAddrtoString(FromAddr.Addr)+' Port : ' -+Inttostr(Swap(FromAddr.Port))); -Connection[ConnectionNumber].Handle := Handle; -Connection[ConnectionNumber].IP := FromAddr.Addr; -Connection[ConnectionNumber].Port := FromAddr.Port; -Connection[ConnectionNumber].Connected := True; -Connection[ConnectionNumber].IdleTimer := 0; -WelcomeHandle(Handle,ConnectionNumber); -End; + FromAddrSize := Sizeof(FromAddr); + If FreeConnections > 0 Then + Begin + ConnectionNumber := GetFreeConnection; + PDebug('Accepting New Connection Number : '+InttoStr(ConnectionNumber)); + Handle := Accept(S,FromAddr,FromAddrSize); + If Handle < 0 Then PError('Accept Error!!'); + PDebug('Accepted From : '+SockAddrtoString(FromAddr.Addr)+' Port : ' + +Inttostr(Swap(FromAddr.Port))); + Connection[ConnectionNumber].Handle := Handle; + Connection[ConnectionNumber].IP := FromAddr.Addr; + Connection[ConnectionNumber].Port := FromAddr.Port; + Connection[ConnectionNumber].Connected := True; + Connection[ConnectionNumber].IdleTimer := 0; + WelcomeHandle(Handle,ConnectionNumber); + End; End; Procedure SetUpSocket; + Var - SockAddr : TInetSockAddr; + SockAddr : TInetSockAddr; + yes : longint; Begin -SockAddr.Family := AF_INET; -SockAddr.Port := Swap(PortNumber); -SockAddr.Addr := 0; -S := Socket(AF_INET,SOCK_STREAM,0); -If SocketError <> 0 then PError('Socket Error : '); -If not Bind(S,SockAddr,SizeOf(SockAddr)) then PError('Bind Error : '); -If not Listen(S,5) then PError('Listen Error : '); + SockAddr.Family := AF_INET; + SockAddr.Port := Swap(PortNumber); + SockAddr.Addr := 0; + S := Socket(AF_INET,SOCK_STREAM,0); + If SocketError <> 0 Then PError('Socket Error : '); + yes := $1010101; {Copied this from existing code. Value is empiric, + but works. (yes=true<>0) } + SetSocketOptions(s, SOL_SOCKET, SO_REUSEADDR,yes,sizeof(yes)); + If Not Bind(S,SockAddr,SizeOf(SockAddr)) Then PError('Bind Error : '); + If Not Listen(S,5) Then PError('Listen Error : '); End; Procedure LoadConnectedFDS; + Var Loop : Integer; Begin -For Loop := 1 to NumberOfConnections Do -If Connection[Loop].Connected then - Begin - FD_SET(Connection[Loop].Handle,FDS); - If Connection[Loop].Handle > GreatestHandle then - GreatestHandle := Connection[Loop].Handle; - End; + For Loop := 1 To NumberOfConnections Do + If Connection[Loop].Connected Then + Begin + FD_SET(Connection[Loop].Handle,FDS); + If Connection[Loop].Handle > GreatestHandle Then + GreatestHandle := Connection[Loop].Handle; + End; End; - Procedure ServiceHandle(Handle, ConnectionNum : Integer); + Var Buffer : String; - Sent, BufferLength : Integer; - -Begin -Writeln('Service Handle : ',Handle); -BufferLength := Recv(Handle,Buffer[1],200,0); -Setlength(Buffer,BufferLength); -If SocketError <> 0 then PDebug('Reciceved Socket Error : ' -+InttoStr(SocketError)+' OnHandle '+InttoStr(Handle)); + Sent, BufferLength : Integer; -If BufferLength = 0 then {It's EOF, Socket has been closed} Begin -PDebug('Socket Handle '+InttoStr(Handle)+' Closed'); -Connection[ConnectionNum].Connected := False; -Shutdown(Handle,2); -fdClose(Handle); -End + Writeln('Service Handle : ',Handle); + BufferLength := Recv(Handle,Buffer[1],200,0); + Setlength(Buffer,BufferLength); + If SocketError <> 0 Then + PDebug('Reciceved Socket Error : ' + +InttoStr(SocketError)+' OnHandle '+InttoStr(Handle)); -Else Begin -PDebug(InttoStr(BufferLength)+' Bytes Recieved'); -{Buffer := Db_Query(Buffer);} -Sent := Send(Handle,Buffer[1],Length(Buffer),0); -If Sent <> Bufferlength then -PDebug('Wanted to Send : '+InttoStr(Length(Buffer))+' Only Sent : '+InttoStr(Sent)); -End; + If BufferLength = 0 Then {It's EOF, Socket has been closed} + Begin + PDebug('Socket Handle '+InttoStr(Handle)+' Closed'); + Connection[ConnectionNum].Connected := False; + Shutdown(Handle,2); + fdClose(Handle); + End + + Else + Begin + PDebug(InttoStr(BufferLength)+' Bytes Recieved'); + {Buffer := Db_Query(Buffer);} + Sent := Send(Handle,Buffer[1],Length(Buffer),0); + If Sent <> Bufferlength Then + PDebug('Wanted to Send : '+InttoStr(Length(Buffer))+' Only Sent : '+InttoStr(Sent)); + End; End; Procedure ServiceSockets; + Var Loop : Integer; Begin -For Loop := 1 to NumberOfConnections do -If Connection[Loop].Connected then - If FD_ISSET(Connection[Loop].Handle,FDS) Then - ServiceHandle(Connection[Loop].Handle,Loop); + For Loop := 1 To NumberOfConnections Do + If Connection[Loop].Connected Then + If FD_ISSET(Connection[Loop].Handle,FDS) Then + ServiceHandle(Connection[Loop].Handle,Loop); -IF FD_ISSET(S,FDS) then AcceptNewConnection; + If FD_ISSET(S,FDS) Then AcceptNewConnection; End; Procedure CloseAllOpen; + Var Loop : Integer; Begin -For Loop := 1 to NumberOfConnections do -Begin -If Connection[Loop].Connected = True then -Begin - Shutdown(Connection[Loop].Handle,1); + For Loop := 1 To NumberOfConnections Do + Begin + If Connection[Loop].Connected = True Then + Begin + Shutdown(Connection[Loop].Handle,1); { fdClose(Connection[Loop].Handle);} {Connection[Loop].Connected := False;} -End; -End; + End; + End; End; -begin -ZeroConnection; {Clear Connected Array} -Quit := False; -PortNumber := 5000; -SetupSocket; -Repeat -FD_ZERO(FDS); -FD_SET(S,FDS); { Socket Looking for new connections } -FD_SET(1,FDS); { Terminal } -GreatestHandle := S; -LoadConnectedFDS; -If Select(GreatestHandle+1,@FDS,nil,nil,1000) > 0 then Begin -ServiceSockets; -If FD_ISSET(1,FDS) then - Begin - PDebug('Reading Console'); - Readln(Command); - If Command='quit' then quit := True; + ZeroConnection; {Clear Connected Array} + Quit := False; + PortNumber := 5000; + SetupSocket; + Repeat + FD_ZERO(FDS); + FD_SET(S,FDS); { Socket Looking for new connections } + FD_SET(1,FDS); { Terminal } + GreatestHandle := S; + LoadConnectedFDS; + If Select(GreatestHandle+1,@FDS,Nil,Nil,1000) > 0 Then + Begin + ServiceSockets; + If FD_ISSET(1,FDS) Then + Begin + PDebug('Reading Console'); + Readln(Command); + If Command='quit' Then quit := True; { Else Writeln(DB_Query(Command));} - Command := ''; - End; -End; -{DB_Tic;} {Updates Database Internals, Needs at Least 1 run per second} -Until Quit = True; -CloseAllOpen; + Command := ''; + End; + End; +{DB_Tic;} {Updates Database Internals, Needs at Least 1 run per second} + Until Quit = True; + CloseAllOpen; -End. +End. \ No newline at end of file