A Traffic Client Server Model
A traffic client server model is a an application of client-server model. It uses the socket programming. I have used C#.net as a front end and SQL Express as a back end. The problem definition and solution is given below:
Download the Full Solution <<
Client Model:
TrafficClient.cs
/***************************************************************
Quazi Mainul Hasan
***************************************************************/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.IO;
using System.Xml;
namespace TrafficClient
{
public partial class TrafficClientServerMenu : Form
{
private static TcpClient m_tcpClient;
private NetworkStream m_networkStream;
private StreamWriter m_streatWriter;
private StreamReader m_streamReader;
// This is the constructor for the class.
public TrafficClientServerMenu()
{
InitializeComponent(); // Initializing component of the form
this.disconnectToolStripMenuItem.Enabled = false; // Disabling the disconnect button initially
}
// This Exit eventhandler will terminate the whole program.
private void ExitToolsStripMenuItem_Click(object sender, EventArgs e)
{
Application.Exit(); //It will terminate the application.
}
private void connectToolStripMenuItem_Click(object sender, EventArgs e)
{
if (portNumberTextBox.Text.Trim().ToString()=="")
{
MessageBox.Show("Set the port number first, the same port address in the server.", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
portNumberTextBox.Focus();
return;
}
try
{
System.Windows.Forms.Cursor.Current = Cursors.WaitCursor; // Show wait cursor in the window
m_tcpClient = new TcpClient("localhost", Int32.Parse(portNumberTextBox.Text.Trim().ToString())); // this will try to connect to the port in the server
this.connectToolStripMenuItem.Enabled = false; //after connection this will disable the connect menu
this.disconnectToolStripMenuItem.Enabled = true; // it will enable the menu strip for disconnection
System.Windows.Forms.Cursor.Current = Cursors.Arrow; // shows the default cursor in the window.
MessageBox.Show("Successfully connected.","Information", MessageBoxButtons.OK, MessageBoxIcon.Information); // Shows confirmation message for successfull connection.
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString(),"Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
//Even handler for disconnect button. This will disconnect the connection betwen client and serve.
private void disconnectToolStripMenuItem_Click(object sender, EventArgs e)
{
MessageBox.Show("Connection disconnected.","Information", MessageBoxButtons.OK, MessageBoxIcon.Information); // Showing message that the connection is disconnected.
this.disconnectToolStripMenuItem.Enabled = false; // Disable the disconnect button
this.connectToolStripMenuItem.Enabled = true; // Enable the connect button
//if (m_tcpClient.Connected)
//{
m_tcpClient.Close(); //this will disconnect the connection with the server from client.
//}
if(m_streamReader != null || m_streatWriter != null || m_networkStream != null) //Checks whther any of them is null or not, if
{
m_streamReader.Close();
m_streatWriter.Close();
m_networkStream.Close();
}
this.roadComboBox.SelectedIndex = -1; // Set the dropdown box to it's initial stage. No selection will be there in the dropdown.
this.outputTrafficTextBox.Text = ""; // Clearing the fields.
this.dataGridView1.DataSource = null; // Reset the datagridview.
}
//event handler for update button, this event handler will request data form the server on a specific road selected from the roadCombobox.
private void updateButton_Click(object sender, EventArgs e)
{
string situationOfRoad="";
if (m_tcpClient==null) //checks whether client is connected to the server or not.
{
MessageBox.Show("Please connect to the server first.", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
if (this.roadComboBox.Text=="") //checks whether a road is selected or not.
{
MessageBox.Show("Please select a road to get the traffic update.","Information",MessageBoxButtons.OK,MessageBoxIcon.Information);
this.roadComboBox.Focus();
return;
}
if (m_tcpClient.Connected)
{
m_networkStream = m_tcpClient.GetStream(); //get a Network stream from the server
m_streamReader = new StreamReader(m_networkStream); // create a stream reader for reading data from the server.
m_streatWriter = new StreamWriter(m_networkStream); // create a stream writer for sending request to the server.
m_streatWriter.WriteLine(roadComboBox.Text.ToString()); //writing data in the stream
m_streatWriter.Flush(); //sending request to the server
situationOfRoad = m_streamReader.ReadLine(); // Get data form the server
this.ShowDataInClientSide(situationOfRoad); // Shoing graphical representation of the traffic data.
outputTrafficTextBox.Text = situationOfRoad;
}
}
private void ShowDataInClientSide(string situationOfRoad)
{
char[] separator ={ ',' };
string[] parsedValue = situationOfRoad.Split(separator); // Parsing the traffic data from the server which is received from the server as a string.
listBox1.Items.Clear(); // Clearing the items in the listbox control.
for (int i = 0; i < parsedValue.Length; i++)
{
listBox1.Items.Add(parsedValue[i].Trim().ToString()); // This loop will add the parsed value in the list box.
}
DataTable trafficStatus= new DataTable("TrafficUpdate"); //Creats a new data table as a datasource for datagridview1
DataColumn col1 = new DataColumn("Intersection", typeof(string)); // Creats a colum with name Intersection of type string
DataColumn col2 = new DataColumn("Status", typeof(Bitmap)); //Creats a column with name Status of type Bitmap
//DataGridTableStyle tableStyle = new DataGridTableStyle();
trafficStatus.Columns.Add(col1);
trafficStatus.Columns.Add(col2); // Adding the columns in the datatable.
for (int i = 0; i < parsedValue.Length; i++)
{
DataRow dr;
if (parsedValue[i].ToString() != "") // Checks whether there is any new line in the parsed value or not.
{
dr = trafficStatus.NewRow(); // Adds a new row to the data table.
dr["Intersection"] = parsedValue[i].Trim().ToString(); // Sets the value of the column Intersection in this new row.
dr["Status"] = DrawBitMap(parsedValue[i]); //Set the bitmap value in the column Status in this row.
trafficStatus.Rows.Add(dr); //Adding the row in the table
}
else continue; // If there is a new line it will no add a row in the data table.
}
trafficStatus.AcceptChanges(); // This function will save the data in the data table and make the status of each row to default instead of added.
this.dataGridView1.DataSource = null; // This will reset the datasource of of the datagridview
dataGridView1.AllowUserToAddRows = false; // This will disable the add row option in the gridview from client side explicitly.
this.dataGridView1.DataSource = trafficStatus; // Sets the data source for the gridview.
dataGridView1.Columns["Status"].Width = 270; // Sets the width of the column status in the gridview.
dataGridView1.Columns["Intersection"].Width = 300; // Sets the width of the column status in the gridview.
}
private Bitmap DrawBitMap(string temp)
{
Bitmap statusBitMap = new Bitmap(250, 20); // Creats a bitmap object with specific width and height.
Color col = new Color();
if (temp.Contains("Normal")) // true, if the parsed string has the value Normal.
{
col = Color.Green; // this will set the color for filling the bitmap.
}
if (temp.Contains("Slow")) // true, if the parsed string has the value Slow
{
col = Color.Navy; // this will set the color for filling the bitmap.
}
if (temp.Contains("Congested")) // true, if the parsed string has the value Congested
{
col = Color.Purple; // this will set the color for filling the bitmap.
}
if (temp.Contains("Accident")) // true, if the parsed string has the value Accident
{
col = Color.Red; // this will set the color for filling the bitmap.
}
// This loop will fill the bitmap with the selected color.
for (int i = 0; i < 250; i++)
{
for (int j = 0; j < 20; j++)
{
statusBitMap.SetPixel(i, j,col); // Set pixel to that a specific color.
}
}
return statusBitMap;
}
}
}
Server Model
TrafficServer.cs
/***************************************************************
Quazi Mainul Hasan
***************************************************************/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.IO;
using System.Timers;
using System.Threading;
namespace TrafficServer
{
public partial class Server : Form
{
private TcpListener m_tcpListener; // Listens in a specific port.
private Socket m_serverSocket; // server socket for creating socket in the server side to connect to the client side.
private NetworkStream m_networkStream; // For exchanging data through steram.
private StreamReader m_streamReader; // for reading data from the stream
private StreamWriter m_streamWriter; // for writing data in the stream
private DataAccessLayer m_dataAccessLayer; // This class is for accessing data to the database.
private System.Timers.Timer m_timer; // timer is used for updating data in the database after a certain interavl.
private double delayTime = 5000; // Initially time interval is set to 5 sec.
private Thread m_WrokerThread; // This thread is used for sending and receiving data
private string dataFromClient; // The client data will be stored in this variable.
/// <summary>
/// Constructor for this class
/// </summary>
public Server()
{
InitializeComponent();
m_timer = new System.Timers.Timer(delayTime); // this instantiate the timer with the interval.
m_timer.Enabled = true; // making timer enables.
m_timer.Elapsed += new ElapsedEventHandler(m_timer_Elapsed); // adding the evenhandler for the timer.
m_timer.Start(); // this will start the timer
m_dataAccessLayer = new DataAccessLayer(); //instantiate an object of dataaccesslayer
}
// This even handler will set the time interval.
private void setTimebutton_Click(object sender, EventArgs e)
{
m_timer.Interval = Convert.ToDouble(this.timeIntervalUpDown.Value);
}
// This event handler will update the traffic data in the database randomly.
void m_timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
m_dataAccessLayer.UpdateData(); // Calls the function update data in the DataAccessLayer class.
}
// This function will be handled by a thread and will handle the client data.
private void WorkerThread()
{
while (true)
{
try
{
dataFromClient = m_streamReader.ReadLine(); // This will wait for the data from the client.
}
catch (Exception ex)
{
MessageBox.Show("Server Disconnected.");
return;
}
if (dataFromClient != null)
{
Console.WriteLine("Traffic request for road" + dataFromClient + " is received");
m_streamWriter.WriteLine(this.GetTrafficInformation(dataFromClient)); // This will write the traffic data in the stream
m_streamWriter.Flush(); // This will send the traffic data to the client
Console.WriteLine("Traffic update for road" + dataFromClient + " is send to client");
}
else
{
m_serverSocket = m_tcpListener.AcceptSocket(); // this will connect to the client through server socket.
m_networkStream = new NetworkStream(m_serverSocket); // The will create a stream for exchanging data between client and server.
m_streamReader = new StreamReader(m_networkStream); // This will create a stream reader
m_streamWriter = new StreamWriter(m_networkStream); // This will create a stream writer.
}
}
}
// This eventhandler will start the server in a specific port and when a client is received it will accept the request and will instantiate a thread to handle the data exchange.
private void startButton_Click(object sender, EventArgs e)
{
string dataFromClient;
if (m_tcpListener == null)
{
if (portTextBox.Text.Trim().ToString()!="")
{
Int32 portNumber = Int32.Parse(portTextBox.Text.Trim().ToString());
if (portNumber < 1024)
{
MessageBox.Show("Port number must be greater than 1024.", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
m_tcpListener = new TcpListener(portNumber); // This will listen to a specific port number
m_tcpListener.Start(); // Server will wait for the client request
MessageBox.Show("Server is started", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
MessageBox.Show("Port number canot be empty", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
portTextBox.Focus();
return;
}
}
responseTextBox.Text = "Waiting for the client request..." + Environment.NewLine;
m_serverSocket = m_tcpListener.AcceptSocket(); // This will create a connection with the client.
m_networkStream = new NetworkStream(m_serverSocket);
m_streamReader = new StreamReader(m_networkStream);
m_streamWriter = new StreamWriter(m_networkStream);
try
{
if (m_serverSocket.Connected) // Checks whether the connection is established or not.
{
responseTextBox.Text += "Connection is established with the client...";
m_WrokerThread = new Thread(new ThreadStart(WorkerThread)); // Creates a new thread for handling data exchange.
m_WrokerThread.Start(); // This will start the thread.
}
else
{
//m_serverSocket.Close();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
finally
{
// m_serverSocket.Close();
}
}
//This function will get the traffic data from the data base.
private string GetTrafficInformation(string dataFromClient)
{
DataTable roadInfoDT = m_dataAccessLayer.SelectData(dataFromClient); // Use the DataAccessLayer class to retrieve data.
string roadCondition = "";
foreach (DataRow row in roadInfoDT.Rows)
{
roadCondition += row["Status"] + " at intersection between " + row["Highway1"].ToString() + " and " + row["Highway2"].ToString() + ", "; // Creating a string for sending over the stream to the client.
}
roadCondition = roadCondition.Remove(roadCondition.Length - 1, 1); // This removes the last comma in the string.
return roadCondition;
}
// This event handler terminate worker thread and will exit the application.
private void Server_FormClosed(object sender, FormClosedEventArgs e)
{
m_WrokerThread.Abort();
Application.Exit();
}
// This event handler closes the server socket and exit application.
private void stopButton_Click(object sender, EventArgs e)
{
if (m_serverSocket != null)
{
m_serverSocket.Close();
}
m_WrokerThread.Abort();
Application.Exit();
}
}
}
Data Access Layer
DataAccessLayer.cs
/***************************************************************
Quazi Mainul Hasan
***************************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.Data.SqlClient;
using System.Data;
using System.Configuration;
namespace TrafficServer
{
/// <summary>
/// This is class used to access data in the database.
/// </summary>
public class DataAccessLayer
{
private string m_connectionString = @"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\TrafficDatabase.mdf;Integrated Security=True;User Instance=True"; // This is the connection string to make connection to the sql database.
private SqlConnection m_sqlConnection; // SqlConnection class is used to establish the connection.
private SqlDataAdapter m_sqlDataAdapter; // SqlDataAdapter is used to fill the dataset based on the select query.
/// <summary>
/// Constructor for the class.
/// </summary>
public DataAccessLayer()
{
m_sqlConnection = new SqlConnection(m_connectionString); // Create a new instance of sqlconnection.
}
/// <summary>
///This function retrives data from the table "RoadInformation," fills the table with data and return that table.
/// </summary>
/// <param name="roadName"></param>
/// <returns></returns>
public DataTable SelectData(string roadName)
{
DataTable roadInfoDT = new DataTable("RoadInfo"); //creates a table with name "RoadInfo"
string selectString = "Select * from RoadInformation where Highway1='" + roadName + "' or Highway2='" + roadName + "'"; // Select query for retreving data.
m_sqlConnection.Open(); //creates a connection with the database.
m_sqlDataAdapter = new SqlDataAdapter(selectString, m_sqlConnection); // Instantiating the sqladapter.
m_sqlDataAdapter.Fill(roadInfoDT); //Fills the table with data from the database.
m_sqlConnection.Close(); //closes the connection with database.
return roadInfoDT;
}
/// <summary>
/// This function updates the table "RoadInformation," randomly.
/// </summary>
public void UpdateData()
{
string updateString = "";
for (int i = 1; i <= 10; i++)
{
updateString = "Update RoadInformation Set Status='" + this.GetRandomStatus() + "', Timestamp='" + DateTime.Now + "' where Id = " + i;
SqlConnection sqlConnection = new SqlConnection(m_connectionString); // Instantiate sql connection object
SqlCommand sqlCommand = new SqlCommand(updateString, sqlConnection); // Instantiate sql command object, which is used for executing query.
try
{
//if (m_sqlConnection.State== ConnectionState.Closed)
//{
sqlConnection.Open();
//}
sqlCommand.ExecuteNonQuery(); // execute the update query.
//if (m_sqlConnection.State == ConnectionState.Open)
//{
sqlConnection.Close();
//}
}
catch (Exception ex)
{
throw ex;
}
}
}
/// <summary>
/// This function returns a status of the road randomly.
/// </summary>
/// <returns></returns>
private string GetRandomStatus()
{
Random rand = new Random();
string status = "";
switch (rand.Next(4)) // this will generate a random number between 0 and 4
{
case 0:
status = Status.Normal.ToString(); //sets the status
break;
case 1:
status = Status.Slow.ToString(); //sets the status
break;
case 2:
status = Status.Congested.ToString(); //sets the status
break;
case 3:
status = Status.Accident.ToString(); //sets the status
break;
default:
break;
}
return status;
}
}
/// <summary>
///This enum is used for defining the status of the road.
/// </summary>
public enum Status
{
Normal,
Slow,
Congested,
Accident,
}
}
Comments
Post a Comment