Code archives/Networking/TCP Socket Server

This code has been declared by its author to be Public Domain code.

Download source code

TCP Socket Server by CoderLaureate
(Posted 21 years ago)
TCPSocketServer

I thought I'd throw my hat into the "TCPSocket Ring". This is an OOP
approach to creating a TCPSocket server. Callbacks are used for extensibility.
You can create functions to handle events and add whatever functionality you
like. You can create many different servers listening to different ports, and
assign different functionality to each server. The benefit of doing this is
that each server is running withing the same process, and therefor causes
less overhead drain on your system resources.

The Event Callback handles are:

NewConnectionCallback

Triggered whenever a new client connects.
The callback function takes one parameter of type TCPSocketConnection.
Your callback function can access the various fields and methods of
the connection. A link back to the connection's server is also provided
to give you access to the various fields and methods of the server.

LostConnectionCallback

Triggered whenever a client disconnects from the server.
This callback also takes a TCPSocketConnection. After the server calls
the callback function it removes the connection from it's collection.

MsgRcvdCallback

Triggered whenever a client sends a message to the server.
The callback function takes one parameter of type TCPSocketConnection.
Your callback function can access the message in the connection object's
"Buffer" field. The field is a string, but can easily be converted to
an array of bytes for whatever processing you need to do. This
function is where you would add any "Intelligence" to your server, ie,
processing commands, etc.

Methods

Broadcast(Message:String, [conn:TCPSocketConnection = Null])

If a TCPSocketConnection is provided the server only broadcasts the message
to that specific connection. Otherwise the server will broadcast the message
to all of it's connections.

Listen()

Updates the server connections and triggers events as they occure.



TCPSocketConnections

A TCPSocketConnection is the "pipeline" through which the server communicates
with the clients that are connected. Each server object has it's own
collection of TCPSocketConnection objects.

Methods

Recieves messages from your program and tells the server to trigger the
MsgRcvdCallback event. This works in a "Non-Blocking" fashion, so as not
to hold up your application while waiting for input. You're program
causes the server to trigger this event by sending a "Stop Sequence". The
server defaults this stop sequence to a Carriange Return/Line Feed {~r~n}.
But you can change it to whatever you want by setting the server's "StopSeq"
field.
Rem

	Title:   TCPSocket Server
	
	Author:  Jim Pishlo  (CoderLaureate)
	            (J9T@Jimmy9Toes.com)
	
End Rem

Strict

Type TCPSocketServer
	
	'Properties
	Field MyPort:Int = 3849
	Field MySocket:TSocket
	Field MyStream:TSocketStream
	Field Connections:TList = New TList
	Field StopSeq:String = "~r~n"
	
	'Callback handles
	Field NewConnectionCallback(Conn:TCPSocketConnection)
	Field MsgRcvdCallback(Conn:TCPSocketConnection)
	Field LostConnectionCallback(Conn:TCPSocketConnection)
	
	'Constructor (for lack of a better word)
	Function Create:TCPSocketServer(_Port:Int = 3849)
		Local s:TCPSocketServer = New TCPSocketServer
		s.MyPort = _Port
		s.MySocket = CreateTCPSocket()
		s.MyStream = CreateSocketStream(s.MySocket)
		s.MySocket.Bind(_Port)
		s.MySocket.Listen(0)
		Return s
	End Function
	
	'The main method.
	'Monitors connections and triggers events.
	Method Listen()
		Local newConn:TSocket = MySocket.Accept(0)
		If newConn <> Null Then
			Local conn:TCPSocketConnection = TCPSocketConnection.Create(Self,newConn)
			'Add the new connection to the collection
			Connections.AddLast(conn)
			'If a callback has been assigned call it.
			If NewConnectionCallback <> Null Then
				NewConnectionCallback(conn)	'Pass a refernce to the new connection
			End If
		End If
		
		'Clean up closed connections
		For Local c:TCPSocketConnection = EachIn Connections
			If Not c.MySocket.Connected() Then
				If LostConnectionCallback <> Null Then
					LostConnectionCallback(c)
				End If
				Connections.Remove(c)	'Remove connection from collection
			End If
		Next
		
		'Receive Data from connections
		'Trigger callback if neccesary
		For Local c:TCPSocketConnection = EachIn Connections
			If c.MySocket.Connected() Then
				Local t:String = c.Receive()
				If t <> "" Then
					If MsgRcvdCallback <> Null Then
						MsgRcvdCallback(c)
						c.Buffer = ""
					End If
				End If
			End If
		Next 
	End Method
	
	Method Broadcast(Message:String, Conn:TCPSocketConnection = Null)
		If Conn <> Null Then
			Conn.Send(Message)
		Else
			Local c:TCPSocketConnection
			For c = EachIn Connections
				If c.MySocket.Connected() Then
					c.Send(Message)
				End If
			Next
		End If	
	End Method
	
End Type

Type TCPSocketConnection
	Field MyID:String
	Field MyServer:TCPSocketServer
	Field MySocket:TSocket
	Field MyStream:TSocketStream
	Field Buffer:String = ""
	Field StopSeq:String
	
	Function Create:TCPSocketConnection(s:TCPSocketServer, NewSocket:TSocket)
		Local c:TCPSocketConnection = New TCPSocketConnection
		c.MyServer = s
		c.MySocket = NewSocket
		c.MyStream = CreateSocketStream(c.MySocket)
		c.StopSeq = c.MyServer.StopSeq
		c.MyID = DottedIP(c.MySocket.RemoteIP())
		Return c
	End Function

	Method Send(Text:String)
		MySTream.WriteString(Text)
	End Method

	Method Receive:String()
		Local nBytes:Int = MySocket.ReadAvail()
		Local s:String = StopSeq
		If nBytes Then
			Local in:String = ReadString(MyStream,nBytes)
			Buffer:+ in
			If Buffer.Length >= s.Length And Right$(Buffer,s.Length) = s Then
				Local t:String = Buffer.Replace(s,"") 'Strip out the stop sequence
				Return t
			End If
		End If
	End Method
	
End Type


Function CreateTCPSocketServer:TCPSocketServer(_Port:Int = 3849)
	Return TCPSocketServer.Create(_Port)
End Function





'Test Code:  This is a simple Telnet Chat Server.  Run this program, then
'            open up a command prompt and type:
'  
'				Telnet localhost 3849
'
'			 You can telnet into this server from anywhere in the world
'            and do *very basic* text chatting.  To log in from another
'            computer, type:
'
'				Telnet {host computer ip} 3849
'
'			 This is just a sample program to show you what you can do
'			 with the TCPSocketServer object.
'----------------------------------------------------------------------

'Create callback functions for interaction with the TCPSocketServer Object.

'Function to handle data recieved by server
'------------------------------------------
Function TextHandler(C:TCPSocketConnection)
	C.MyServer.BroadCast(C.MyID + ": " + C.Buffer)
End Function

'Greet new users and assign an ID
'--------------------------------
Function Greet(C:TCPSocketConnection)
	C.MyID = "User [" + MilliSecs() + "]"
	C.MyServer.BroadCast("Welcome!~r~n",C)
	C.MyServer.BroadCast(C.MyID + " has entered the room.~r~n")	
End Function

'Alert other users when a user leaves
'------------------------------------
Function LostConnection(C:TCPSocketConnection)
	C.MyServer.BroadCast("~r~n" + C.MyID + " has left the room.~r~n~r~n")
End Function

'Create an Instance of the TCPSocketServer Class
'-------------------------------------------------
Global Server:TCPSocketServer = CreateTCPSocketServer()

'Assign Function Pointers to Server's callback handles
'-----------------------------------------------------
Server.MsgRcvdCallback = TextHandler
Server.NewConnectionCallback = Greet
Server.LostConnectionCallback = LostConnection


'The Main Loop
'--------------
While Not KeyHit(KEY_ESCAPE)
	Server.Listen()		'That's it!
Wend