瀏覽代碼

* added setsocketoptions + pulled it through source beautifier

marco 25 年之前
父節點
當前提交
ab086a8e20
共有 1 個文件被更改,包括 182 次插入165 次删除
  1. 182 165
      docs/sockex/serverex.pp

+ 182 - 165
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
  [email protected]
   ***************************************************************************}
- 
+
+{$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;
-Begin
-Result := 0;
-Loop := 1;
-Found := False;
-While (Loop < NumberOfConnections + 1) and (Not Found) do
+   Found : Boolean;
 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
-
-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;
+ 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));
+
+ 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.