Created
June 9, 2015 11:14
-
-
Save Jalalx/78813cf6eb0914ab36cc to your computer and use it in GitHub Desktop.
Represents Client and Server classes to communicate in TCP/IP networks.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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