Skip to content

Instantly share code, notes, and snippets.

@Jalalx
Created June 9, 2015 11:14
Show Gist options
  • Save Jalalx/78813cf6eb0914ab36cc to your computer and use it in GitHub Desktop.
Save Jalalx/78813cf6eb0914ab36cc to your computer and use it in GitHub Desktop.
Represents Client and Server classes to communicate in TCP/IP networks.
using System;
using System.Net;
using System.Threading;
namespace System.Net.Sockets
{
public class Client
{
// Fields...
private Socket clientSocket = null;
private IPEndPoint destination = null;
private byte[] sendBuffer, recvBuffer;
private Thread readThread;
private ProtocolType sockProtocol;
private SocketType sockType;
private int rc;
//private int remotePort = 5150;
private int bufferSize = 4096;
// Events
public event DataReceivedEventHandler DataReceived;
public event CommunicationErrorEventHandler CommunicationError;
public event CommunicationMessageHandler CommunicationMessage;
// Event Methods
public virtual void OnDataReceived(DataReceivedEventArgs e)
{
if (DataReceived != null)
DataReceived(e);
}
public virtual void OnCommunicationError(CommunicationErrorEventArgs e)
{
if (CommunicationError != null)
CommunicationError(e);
}
public virtual void OnCommunicationMessage(CommunicationMessageEventArgs e)
{
if (CommunicationMessage != null)
CommunicationMessage(e);
}
public Client()
: this("127.0.0.1", 5150)
{
}
public Client(string ipAddress, int port)
{
this.destination = new IPEndPoint(IPAddress.Parse(ipAddress), port);
}
public Client(IPAddress address, int port)
{
this.destination = new IPEndPoint(address, port);
}
public Client(IPEndPoint endPoint)
{
this.destination = endPoint;
}
// Methods...
/// <summary>
/// This routine repeatedly copies a string message into a byte array until filled.
/// </summary>
/// <param name="dataBuffer">Byte buffer to fill with string message</param>
static public void FormatBuffer(byte[] dataBuffer, string message)
{
if (string.IsNullOrEmpty(message))
return;
byte[] byteMessage = System.Text.Encoding.ASCII.GetBytes(message);
int index = 0;
// First convert the string to bytes and then copy into send buffer
while (index < byteMessage.Length)
{
for (int j = 0; j < dataBuffer.Length; j++)
{
// Make sure another byte of data buffer became zero
if (index >= byteMessage.Length)
{
dataBuffer[j] = 0;
}
else
{
dataBuffer[j] = byteMessage[index];
index++;
}
}
}
}
/// <summary>
/// This is the main function for the simple client. It parses the command line and creates
/// a socket of the requested type. For TCP, it will resolve the name and attempt to connect
/// to each resolved address until a successful connection is made. Once connected a request
/// message is sent followed by shutting down the send connection. The client then receives
/// data until the server closes its side at which point the client socket is closed. For
/// UDP, the socket is created and if indicated connected to the server's address. A single
/// request datagram message. The client then waits to receive a response and continues to
/// do so until a zero byte datagram is receive which indicates the end of the response.
/// </summary>
public void RunClient()
{
sockType = SocketType.Stream;
sockProtocol = ProtocolType.Tcp;
int rc;
// Specified TCP
sockType = SocketType.Stream;
sockProtocol = ProtocolType.Tcp;
sendBuffer = new byte[bufferSize];
recvBuffer = new Byte[bufferSize];
try
{
clientSocket = new Socket(AddressFamily.InterNetwork, sockType, sockProtocol);
try
{
//StatusLabel1.Text = "Attempting connection to: " + destination.ToString();
OnCommunicationMessage(new CommunicationMessageEventArgs("Attempting connection to: "
+ destination.ToString()));
clientSocket.Connect(destination);
if (clientSocket != null)
// StatusLabel1.Text = "Connection to Server on " + destination.ToString();
OnCommunicationMessage(new CommunicationMessageEventArgs("Connection to Server on " +
destination.ToString()));
}
catch (SocketException errr)
{
// Connect faile so close the socket and try the next address
//StatusLabel1.Text = errr.Message;
clientSocket.Close();
clientSocket = null;
//BtnDC_Click(null, null);
Disconnect();
OnCommunicationError(new CommunicationErrorEventArgs(errr));
}
// Make sure we have a valid socket before trying to use it
if (clientSocket != null)
{
// Receive data in a loop until the server closes the connection. For
// TCP this occurs when the server performs a shutodwn or closes
// the socket. For UDP, we'll know to exit when the remote host
// sends a zero byte datagram.
while (true)
{
rc = clientSocket.Receive(recvBuffer);
//StatusLabel1.Text = "Read " + rc + " bytes";
OnCommunicationMessage(new CommunicationMessageEventArgs("Read " + rc + " bytes"));
if (rc > 0)
{
//TxtbxRcv.Text += System.Text.Encoding.ASCII.GetString(recvBuffer);
OnDataReceived(new DataReceivedEventArgs(recvBuffer));
}
// Exit loop if server indicates shutdown
if (rc == 0)
{
clientSocket.Close();
break;
}
}
}
else
{
//StatusLabel1.Text = "Unable to establish connection to server!";
OnCommunicationMessage(new CommunicationMessageEventArgs("Unable to establish connection to server!"));
//BtnDC_Click(null, null);
Disconnect();
}
}
catch (SocketException err)
{
clientSocket.Close();
//BtnDC_Click(null, null);
//StatusLabel1.Text = err.Message;
Disconnect();
OnCommunicationError(new CommunicationErrorEventArgs(err));
}
}
public void Send(string textMessage)
{
try
{
// Format the string message into the send buffer
FormatBuffer(sendBuffer, textMessage + "\r\n");
// Send the request to the server
rc = clientSocket.Send(sendBuffer);
OnCommunicationMessage(new CommunicationMessageEventArgs("Sent request of " + rc + " bytes "));
}
catch (Exception ex)
{
OnCommunicationError(new CommunicationErrorEventArgs(ex));
}
}
public void Exit()
{
// For TCP, shutdown sending on our side since the client won't send any more data
//BtnDC_Click(null, null);
Disconnect();
//Application.ExitThread();
//System.Environment.Exit(System.Environment.ExitCode);
//Application.Exit();
}
public void Connect()
{
readThread = new Thread(new ThreadStart(RunClient));
readThread.Start();
//BtnDC.Enabled = true;
//BtnSnd.Enabled = true;
//BtnConnect.Enabled = false;
}
public void Disconnect()
{
try
{
if (clientSocket != null)
{// For TCP, shutdown sending on our side since the client won't send any more data
clientSocket.Shutdown(SocketShutdown.Send);
}
}
catch (Exception err)
{
//StatusLabel1.Text = err.Message;
OnCommunicationError(new CommunicationErrorEventArgs(err));
}
//BtnConnect.Enabled = true;
//BtnSnd.Enabled = false;
}
}
public class Server
{
public event CommunicationMessageHandler CommunicationMessage;
public event CommunicationErrorEventHandler CommunicationError;
public event DataReceivedEventHandler DataReceived;
private int localPort = 5150;// Port number for the destination
private int sendCount = 1;// Number of times to send the response
private int bufferSize = 4096;// Size of the send and receive buffers
private IPAddress localAddress = IPAddress.Any;
private SocketType sockType;
private ProtocolType sockProtocol;
private int rc;
private Thread clientThread;
private Socket clientSocket;
private Socket serverSocket = null;
private byte[] receiveBuffer, sendBuffer;
public Server(int localPort)
{
this.localPort = localPort;
clientThread = new Thread(new ThreadStart(RunServer));
clientThread.Start();
}
public Server()
: this(5150)
{
}
/// <summary>
/// This routine repeatedly copies a string message into a byte array until filled.
/// </summary>
/// <param name="dataBuffer">Byte buffer to fill with string message</param>
/// <param name="message">String message to copy</param>
public static void FormatBuffer(byte[] dataBuffer, string message)
{
byte[] byteMessage = System.Text.Encoding.ASCII.GetBytes(message);
int index = 0;
// Make sure another byte of data buffer became zero
while (index < byteMessage.Length)
{
for (int j = 0; j < dataBuffer.Length; j++)
{
if (index >= byteMessage.Length)
{
dataBuffer[j] = 0;
}
else
{
dataBuffer[j] = byteMessage[index];
index++;
}
}
}
}
public virtual void OnDataReceived(DataReceivedEventArgs e)
{
if (DataReceived != null)
DataReceived(e);
}
public virtual void OnCommunicationError(CommunicationErrorEventArgs e)
{
if (CommunicationError != null)
CommunicationError(e);
}
public virtual void OnCommunicationMessage(CommunicationMessageEventArgs e)
{
if (CommunicationMessage != null)
CommunicationMessage(e);
}
/// <summary>
/// it creates a listening socket and waits to accept a client
/// connection. Once a client connects, it waits to receive a "request" message. The
/// request is terminated by the client shutting down the connection. After the request is
/// received, the server sends a response followed by shutting down its connection and
/// closing the socket.
/// </summary>
public void RunServer()
{
// Local interface to bind to
localAddress = IPAddress.Parse("127.0.0.1");
receiveBuffer = new byte[bufferSize];
sendBuffer = new byte[bufferSize];
// Specified TCP
sockType = SocketType.Stream;
sockProtocol = ProtocolType.Tcp;
try
{
IPEndPoint localEndPoint = new IPEndPoint(localAddress, localPort);
//IPEndPoint senderAddress = new IPEndPoint(localAddress, 0);
// Create the server socket
serverSocket = new Socket(localAddress.AddressFamily, sockType, sockProtocol);
// Bind the socket to the local interface specified
serverSocket.Bind(localEndPoint);
string StrMessage = sockProtocol.ToString() + " server socket bound to " + localEndPoint.ToString();
//StatusLabel1.Text = StrMessage;
OnCommunicationMessage(new CommunicationMessageEventArgs(StrMessage));
// If TCP socket, set the socket to listening
serverSocket.Listen(1);
}
catch (SocketException err)
{
//StatusLabel1.Text = "Socket error occured: " + err.Message;
OnCommunicationError(new CommunicationErrorEventArgs(err));
}
finally
{
// Close the socket if necessary
//if (serverSocket != null)
// serverSocket.Close();
}
try
{
// Service clients in a loop
while (true)
{
// Wait for a client connection
clientSocket = serverSocket.Accept();
//StatusLabel1.Text = "Accepted connection from: " + clientSocket.RemoteEndPoint.ToString();
OnCommunicationMessage(new CommunicationMessageEventArgs("Accepted connection from: " + clientSocket.RemoteEndPoint.ToString()));
//if (clientSocket != null)
// BtnSnd.Enabled = true;
while (true)
{
rc = clientSocket.Receive(receiveBuffer);
//StatusLabel1.Text = "Read " + rc + " bytes";
OnCommunicationMessage(new CommunicationMessageEventArgs("Read " + rc + " bytes"));
if (rc > 0)
//TxtbxRcv.Text += System.Text.Encoding.ASCII.GetString(receiveBuffer);
OnDataReceived(new DataReceivedEventArgs(receiveBuffer));
if (rc == 0)
break;
}
}
}
catch (SocketException err)
{
//StatusLabel1.Text = err.Message;
clientSocket.Close();
//BtnSnd.Enabled = false;
OnCommunicationError(new CommunicationErrorEventArgs(err));
}
}
public void Send(string textMessage)
{
// Text message to put into the send buffer
//string textMessage = TxtbxSnd.Text.Trim();
// Format the string message into the send buffer
FormatBuffer(sendBuffer, textMessage + "\r\n");
try
{
// Send the indicated number of response messages
if (serverSocket != null)
for (int i = 0; i < sendCount; i++)
{
rc = clientSocket.Send(sendBuffer);
//StatusLabel1.Text = "Sent " + rc + " bytes";
OnCommunicationMessage(new CommunicationMessageEventArgs("Sent " + rc + " bytes"));
}
}
catch (Exception err)
{
//StatusLabel1.Text = err.Message;
OnCommunicationError(new CommunicationErrorEventArgs(err));
}
//TxtbxSnd.Clear();
}
public void Exit()
{
try
{
// Shutdown the client connection
if (clientSocket != null)
{
clientSocket.Shutdown(SocketShutdown.Send);
clientSocket.Close();
}
}
catch (Exception err)
{
//MessageBox.Show("Error in exiting \n" + err.Message);
OnCommunicationError(new CommunicationErrorEventArgs(err));
}
}
}
public delegate void CommunicationErrorEventHandler(CommunicationErrorEventArgs e);
public class CommunicationErrorEventArgs
{
public Exception Exception { get; set; }
public CommunicationErrorEventArgs(Exception ex)
{
this.Exception = ex;
}
}
public delegate void DataReceivedEventHandler(DataReceivedEventArgs e);
public class DataReceivedEventArgs
{
public byte[] ReceivedData { get; private set; }
public DataReceivedEventArgs(byte[] receivedData)
{
this.ReceivedData = receivedData;
}
}
public delegate void ClientConnectionRequestHandler(ClientConnectionRequestEventArgs e);
public class ClientConnectionRequestEventArgs
{
public EndPoint EndPoint { get; private set; }
public ClientConnectionRequestEventArgs(EndPoint endpoint)
{
this.EndPoint = endpoint;
}
}
public delegate void CommunicationMessageHandler(CommunicationMessageEventArgs e);
public class CommunicationMessageEventArgs
{
public string Message { get; private set; }
public CommunicationMessageEventArgs(string message)
{
this.Message = message;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment