ChatClient
Form1.cs
[code]
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;
using System.Net.Sockets;
using System.IO;
using System.Threading;
using System.Security.Cryptography;
namespace ChatClient
{
public partial class Form1: Form
{
// Will hold the user name
private string UserName = «Unknown»;
private StreamWriter swSender;
private StreamReader srReceiver;
private TcpClient tcpServer;
// Needed to update the form with messages from another thread
private delegate void UpdateLogCallback(string strMessage);
private delegate void UpdateKeysCallback(string keyMsg);
// Needed to set the form to a «disconnected» state from another thread
private delegate void CloseConnectionCallback(string strReason);
private Thread thrMessaging;
private IPAddress ipAddr;
private IPHostEntry ipHost;
private bool Connected;
RSACryptoServiceProvider rsaClientKeys;
RSACryptoServiceProvider rsaServerPublicKey = new RSACryptoServiceProvider(2048);
public Form1()
{
// On application exit, don't forget to disconnect first
Application.ApplicationExit += new EventHandler(OnApplicationExit);
InitializeComponent();
}
// The event handler for application exit
public void OnApplicationExit(object sender, EventArgs e)
{
if (Connected == true)
{
// Closes the connections, streams, etc.
Connected = false;
swSender.Close();
srReceiver.Close();
tcpServer.Close();
}
}
private void btnConnect_Click(object sender, EventArgs e)
{
// If we are not currently connected but awaiting to connect
if (Connected == false)
{
// Initialize the connection
InitializeConnection();
}
else // We are connected, thus disconnect
{
CloseConnection(«Disconnected at user's request.»);
}
}
private void InitializeConnection()
{
rsaClientKeys = new RSACryptoServiceProvider(2048);
//rsaClientPublicKey = new RSACryptoServiceProvider(2048);
//rsaClientPublicKey.FromXmlString(rsaClientPrivateKey.ToXmlString(false));
// Parse the IP address from the TextBox into an IPAddress object
ipAddr = IPAddress.Parse(txtIp.Text);
// Start a new TCP connections to the chat server
//tcpServer = new TcpClient();
//TcpClient tcpServer = new TcpClient(ip.ToString(), 8888);
//tcpServer.Connect(ipAddr, 1986);
//if (tcpServer.Connected == false) return;
ipHost = Dns.Resolve(txtIp.Text);
ipAddr = ipHost.AddressList[0];
try
{
tcpServer = new TcpClient(ipAddr.ToString(), 1986);
Connected = true;
}
catch
{
return;
}
// Helps us track whether we're connected or not
// Prepare the form
UserName = txtUser.Text;
// Disable and enable the appropriate fields
txtIp.Enabled = false;
txtUser.Enabled = false;
txtMessage.Enabled = true;
btnSend.Enabled = true;
btnConnect.Text = «Disconnect»;
// Send the desired username to the server
swSender = new StreamWriter(tcpServer.GetStream());
swSender.WriteLine(txtUser.Text + "|" + rsaClientKeys.ToXmlString(false));
swSender.Flush();
// Start the thread for receiving messages and further communication
thrMessaging = new Thread(new ThreadStart(ReceiveMessages));
thrMessaging.Start();
}
private void ReceiveMessages()
{
// Receive the response from the server
srReceiver = new StreamReader(tcpServer.GetStream());
// If the first character of the response is 1, connection was successful
string ConResponse = srReceiver.ReadLine();
// If the first character is a 1, connection was successful
if (ConResponse[0] == '1')
{
String[] serverResponse = ConResponse.Split('|');
if (serverResponse[0] == «1» && serverResponse[1] != "")
this.Invoke(new UpdateKeysCallback(this.UpdateKeys), new object[] { serverResponse[1] });
// Update the form to tell it we are now connected
this.Invoke(new UpdateLogCallback(this.UpdateLog), new object[] { «msg:connected» });
}
else // If the first character is not a 1 (probably a 0), the connection was unsuccessful
{
string Reason = «Not Connected: »;
// Extract the reason out of the response message. The reason starts at the 3rd character
Reason += ConResponse.Substring(2, ConResponse.Length — 2);
// Update the form with the reason why we couldn't connect
this.Invoke(new CloseConnectionCallback(this.CloseConnection), new object[] { Reason });
// Exit the method
return;
}
//String dataString;
// While we are successfully connected, read incoming lines from the server
while (Connected) //while (Connected && (dataString = srReceiver.ReadLine()) != "")
{
//MessageBox.Show(null, dataString, «Client datastring»);
// Show the messages in the log TextBox
//if (dataString != null)
this.Invoke(new UpdateLogCallback(this.UpdateLog), new object[] { srReceiver.ReadLine() });
//dataString = null;
}
}
// This metod is called from different thread in order to add server key in to crypto stream
private void UpdateKeys(String keyMsg)
{
rsaServerPublicKey.FromXmlString(keyMsg);
//MessageBox.Show(null, keyMsg, «Client F# UpdateKeys M# Server Public Key»);
}
// This method is called from a different thread in order to update the log TextBox
private void UpdateLog(string strMessage)
{
if (strMessage == «msg:connected»)
{
txtLog.AppendText(«Connected Successfully!\r\nYou can talking.:\r\n»);
}
else
{
UTF8Encoding utf8 = new UTF8Encoding();
//String messageFromServer = ;//Convert.FromBase64String(txtCryptoText.Text.Trim()
// Append text also scrolls the TextBox to the bottom each time
txtLog.AppendText(utf8.GetString(rsaClientKeys.Decrypt(Convert.FromBase64String(strMessage), false)) + "\r\n");
}
}
// Closes a current connection
private void CloseConnection(string Reason)
{
// Show the reason why the connection is ending
txtLog.AppendText(Reason + "\r\n");
// Enable and disable the appropriate controls on the form
txtIp.Enabled = true;
txtUser.Enabled = true;
txtMessage.Enabled = false;
btnSend.Enabled = false;
btnConnect.Text = «Connect»;
// Close the objects
Connected = false;
swSender.Close();
srReceiver.Close();
tcpServer.Close();
thrMessaging.Abort();
}
// Sends the message typed in to the server
private void SendMessage(String keysMessage = «0|0»)
{
if (txtMessage.Lines.Length >= 1)
{
UTF8Encoding utf8 = new UTF8Encoding();
swSender.WriteLine(Convert.ToBase64String(rsaServerPublicKey.Encrypt(utf8.GetBytes(txtMessage.Text), false)));
swSender.Flush();
txtMessage.Lines = null;
}
txtMessage.Text = "";
}
// We want to send the message when the Send button is clicked
private void btnSend_Click(object sender, EventArgs e)
{
SendMessage();
}
// But we also want to send the message once Enter is pressed
private void txtMessage_KeyPress(object sender, KeyPressEventArgs e)
{
// If the key is Enter
if (e.KeyChar == (char)13)
{
SendMessage();
}
}
}
}
[/code]
Program.cs
[code]
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace ChatClient
{
static class Program
{
/// /// The main entry point for the application.
///
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
[/code]