You are on page 1of 20

i Hc Quc Gia Thnh Ph H Ch Minh

Trng i hc Cng ngh Thng tin

Lp K2C6

Hng dn chi tit lm 1 chng trnh Chat n gin


Gio vin hng dn: Phm Thi Vng

I. Gii thiu chung v cu trc.


-

Chat theo m hnh Client-Server, s dng giao thc TCP.


n v truyn thng tin l Command.
S dng cc namespace chnh l:
o System.Net;
o System.Net.Sockets;
o System.CompomentModel;

II. Hng dn chi tit:


1. Lp trnh Server:
Bc 1: vo Visual C# to 1 project mi c tn l UITChatServer, c dng l
Windows Form. t tn cho class chnh l frmServer. Tip tc trn Solution hin ti to
thm 2 project c dng Class Library t tn l Command v Server.
Bc 2: vo project Command to 2 file c tn l Enum.cs v Command.cs.
Bc 3: m file Enum.cs nhp vo on code sau y nh ngha cc loi
command s dng, khi mun update th cn ch ni dng ca file ny.
public enum CommandType
{
Message,// gi message
ClientList,// gi danh sch client online
NameExists,// thng bo tn va ng nhp c ngi s dng
Login, //thng bo ng nhp
Logout,//thng bo ng xut
}

Bc 4: M file Command.cs v nhp vo on code sau dng nh ngha 1 i


tng command dng truyn trn mng, gm c CommandType, SenderName,
SenderIP, TargerIP,
using System.Net;
namespace UITChat

public class Command


{
private IPAddress senderIP;// a ch IP my gi
public IPAddress SenderIP
{
get { return senderIP; }
set { senderIP = value; }
}
private string senderName;//tn ngi gi
public string SenderName
{
get { return senderName; }
set { senderName = value; }
}
private CommandType cmdType;//loi Command c gi
public CommandType CommandType
{
get { return cmdType; }
set { cmdType = value; }
}
private IPAddress target;// a ch IP my nhn
public IPAddress Target
{
get { return target; }
set { target = value; }
}

private string commandBody;//ni dung cn gi


public string MetaData
{
get { return commandBody; }
set { commandBody = value; }
}
// 2 contructor
public Command(CommandType type, IPAddress targetMachine, string
metaData)
{
this.cmdType = type;
this.target = targetMachine;
this.commandBody = metaData;
}
public Command(CommandType type, IPAddress targetMachine)
{
this.cmdType = type;
this.target = targetMachine;
this.commandBody = "";
}
}
}

Bc 5: Chuyn sang project Server. Ta Reference n project Command. To 3


file l ClientManager.cs , Server.cs v EventArgs.cs

Bc 6: M file EventArgs.cs, nhp vo ni dung sau, nh ngha cc class tha k


t class EventArg v cc delegate dng khai bo cc Event trong 2 file cn li.
using System;
using System.Net;
using System.Net.Sockets;
using UITChat;//ch phi using n class command
namespace Server
{
public delegate void UserOnlineHandler(object sender, UserEventArg user);
public delegate void UserLogoutHandler(object sender, UserEventArg user);
public delegate void CommandReceivedEventHandler(object sender,CommandEventArgs e);
public delegate void DisconnectedEventHandler(object sender, ClientEventArgs e);
public class UserEventArg : EventArgs
{
private string _userName;//tn ngi dng
private IPAddress _ipaddress;//a ch IP
public string UserName
{
get
{
return _userName;
}
set
{
_userName = value;
}
}
public UserEventArg(string Name)
{
_ipaddress = null;
_userName = Name;
}
public UserEventArg(IPAddress address, string Name)
{
_ipaddress = address;
_userName = Name;
}
}
public class CommandEventArgs : EventArgs
{
private Command command;// i tng Command
public Command Command
{
get { return command; }
}
public CommandEventArgs(Command cmd)
{
this.command = cmd;
}
}
public class ClientEventArgs : EventArgs
{
private Socket socket; //Socket ca client
public IPAddress IP
{
get { return ((IPEndPoint)this.socket.RemoteEndPoint).Address; }
}
public int Port
{

get { return ((IPEndPoint)this.socket.RemoteEndPoint).Port; }


}
public ClientEventArgs(Socket clientManagerSocket)
{
this.socket = clientManagerSocket;
}
}
}

Bc 7: M file ClientManager.cs, ta to 1 class c tn l ClientManager. Trong


class ny ta khai bo 1 s thuc tnh v contructor nh sau:
public IPAddress IP
{
get
{
try
{
return ((IPEndPoint)this.socket.RemoteEndPoint).Address;
}
catch
{
return IPAddress.None;
}
}
}
public int Port
{
get
{
if (this.socket != null)
return ((IPEndPoint)this.socket.RemoteEndPoint).Port;
else
return -1;
}
}
private Socket socket;//socket kt ni ti client
private string clientName = "";//tn ca client
public string ClientName
{
get { return this.clientName; }
set { this.clientName = value; }
}
private NetworkStream networkStream;//lun ghi v c d liu trn socket
private BackgroundWorker bwReceiver;//thread nhn
#region Constructor
public ClientManager(Socket clientSocket)
{
this.socket = clientSocket;
this.networkStream = new NetworkStream(this.socket);
this.bwReceiver = new BackgroundWorker();
this.bwReceiver.DoWork += new DoWorkEventHandler(Receive);
this.bwReceiver.RunWorkerAsync();

}
#endregion

Bc 8: Ta vit hm Receive chy trn Thread bwReceiver. Ch ta dng


Encoding chuyn d liu sang kiu d liu c trc khi Encode pha my gi.
y l hm chy Event DoWorkEventHandler trong BackgroudWorker. Mt
class k tha t Thread, gip lm vic trn Thread n gin hn.
private void Receive(object sender, DoWorkEventArgs e)
{
while (this.socket.Connected)
{
try
{
//c commandtype
byte[] buffer = new byte[4];
int readBytes = this.networkStream.Read(buffer, 0, 4);
if (readBytes == 0)
break;
CommandType cmdType = (CommandType)(BitConverter.ToInt32(buffer, 0));
//c kch thc ca SenderIP
buffer = new byte[4];
readBytes = this.networkStream.Read(buffer, 0, 4);
if (readBytes == 0)
break;
int senderIPSize = BitConverter.ToInt32(buffer, 0);
//---------------------//c senderIP
buffer = new byte[senderIPSize];
readBytes = this.networkStream.Read(buffer, 0, senderIPSize);
if (readBytes == 0)
break;
IPAddress senderIP =
IPAddress.Parse(System.Text.Encoding.ASCII.GetString(buffer));
//c kch thc ca SenderName
buffer = new byte[4];
readBytes = this.networkStream.Read(buffer, 0, 4);
if (readBytes == 0)
break;
int senderNameSize = BitConverter.ToInt32(buffer, 0);
//c SenderName
buffer = new byte[senderNameSize];
readBytes = this.networkStream.Read(buffer, 0, senderNameSize);
if (readBytes == 0)
break;
string senderName = System.Text.Encoding.Unicode.GetString(buffer);
//-------------------------//c kch thc ca TargetIp
string cmdTarget = "";
buffer = new byte[4];
readBytes = this.networkStream.Read(buffer, 0, 4);
if (readBytes == 0)
break;
int ipSize = BitConverter.ToInt32(buffer, 0);
//c TargerIp
buffer = new byte[ipSize];
readBytes = this.networkStream.Read(buffer, 0, ipSize);

if (readBytes == 0)
break;
cmdTarget = System.Text.Encoding.ASCII.GetString(buffer);
//c kch thc ca Metadata
string cmdMetaData = "";
buffer = new byte[4];
readBytes = this.networkStream.Read(buffer, 0, 4);
if (readBytes == 0)
break;
int metaDataSize = BitConverter.ToInt32(buffer, 0);
//c metadata
buffer = new byte[metaDataSize];
readBytes = this.networkStream.Read(buffer, 0, metaDataSize);
if (readBytes == 0)
break;
cmdMetaData = System.Text.Encoding.Unicode.GetString(buffer);
//ng gi thnh kiu command
Command cmd = new Command(cmdType, IPAddress.Parse(cmdTarget), cmdMetaData);
cmd.SenderIP = this.IP;
cmd.SenderName = this.ClientName;
//pht s kin nhn xong 1 command
this.OnCommandReceived(new CommandEventArgs(cmd));
}
catch
{
break;//gp bt k li no s t thot
}
}
//pht s kin mt kt ni
this.OnDisconnected(new ClientEventArgs(this.socket));
//ngt kt ni
this.Disconnect();
}

Bc 9: Ta vit hm SendCommand gi 1 command n Client m n qun l.


Qu trnh gi cng c thc hin trn 1 Thread ring, l 1 i tng
BackgroundWorker. Ch cc hm x l s kin cho i tng ny c trnh by
di hm SendCommand.
public void SendCommand(Command cmd)
{
if (this.socket != null && this.socket.Connected)
{
BackgroundWorker bwSender = new BackgroundWorker();
bwSender.DoWork += new DoWorkEventHandler(bwSender_DoWork);
bwSender.RunWorkerCompleted += new
RunWorkerCompletedEventHandler(bwSender_RunWorkerCompleted);
bwSender.RunWorkerAsync(cmd);
}
}
private void bwSender_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
//dn rc sau khi gi xong
((BackgroundWorker)sender).Dispose();

GC.Collect();

private void bwSender_DoWork(object sender, DoWorkEventArgs e)


{
Command cmd = (Command)e.Argument;
e.Result = this.SendCommandToClient(cmd);
}
//S dng semaphor trnh xung t khi gi
System.Threading.Semaphore semaphor = new System.Threading.Semaphore(1, 1);
private bool SendCommandToClient(Command cmd)
{
try
{
semaphor.WaitOne();
//Type
byte[] buffer = new byte[4];
buffer = BitConverter.GetBytes((int)cmd.CommandType);
this.networkStream.Write(buffer, 0, 4);
this.networkStream.Flush();
//Sender IP
byte[] senderIPBuffer = Encoding.ASCII.GetBytes(cmd.SenderIP.ToString());
buffer = new byte[4];
buffer = BitConverter.GetBytes(senderIPBuffer.Length);
this.networkStream.Write(buffer, 0, 4);
this.networkStream.Flush();
this.networkStream.Write(senderIPBuffer, 0, senderIPBuffer.Length);
this.networkStream.Flush();
//Sender Name
byte[] senderNameBuffer =
Encoding.Unicode.GetBytes(cmd.SenderName.ToString());
buffer = new byte[4];
buffer = BitConverter.GetBytes(senderNameBuffer.Length);
this.networkStream.Write(buffer, 0, 4);
this.networkStream.Flush();
this.networkStream.Write(senderNameBuffer, 0, senderNameBuffer.Length);
this.networkStream.Flush();
//Target
byte[] ipBuffer = Encoding.ASCII.GetBytes(cmd.Target.ToString());
buffer = new byte[4];
buffer = BitConverter.GetBytes(ipBuffer.Length);
this.networkStream.Write(buffer, 0, 4);
this.networkStream.Flush();
this.networkStream.Write(ipBuffer, 0, ipBuffer.Length);
this.networkStream.Flush();
//Meta Data.
if (cmd.MetaData == null || cmd.MetaData == "")
cmd.MetaData = "\n";
byte[] metaBuffer = Encoding.Unicode.GetBytes(cmd.MetaData);
buffer = new byte[4];
buffer = BitConverter.GetBytes(metaBuffer.Length);
this.networkStream.Write(buffer, 0, 4);
this.networkStream.Flush();

this.networkStream.Write(metaBuffer, 0, metaBuffer.Length);
this.networkStream.Flush();
semaphor.Release();
return true;

}
catch
{
semaphor.Release();
return false;
}

Bc 10: Tip tc vit thm hm Disconnect ngt kt ni, ng socket v cc


Event .
public bool Disconnect()
{
if (this.socket != null && this.socket.Connected)
{
try
{
this.socket.Shutdown(SocketShutdown.Both);
this.socket.Close();
return true;
}
catch
{
return false;
}
}
else
return true;
}
public event CommandReceivedEventHandler CommandReceived;
protected virtual void OnCommandReceived(CommandEventArgs e)
{
if (CommandReceived != null)
CommandReceived(this, e);
}
public event DisconnectedEventHandler Disconnected;
protected virtual void OnDisconnected(ClientEventArgs e)
{
if (Disconnected != null)
Disconnected(this, e);
}

Bc 11: Chuyn qua file Server.cs v lp trnh cc chc nng c bn cho 1 server
chat. Bao gm forward tin nhn, qun l cc client, v cc hm h tr.
Trc tin l khai bo cc thuc tnh nh sau:
private List<ClientManager> listClient;//danh sach cc client online
private Socket listenerSocket;//socket nghe cc kt ni mi
private int port = 1024;//port c nh nhn Command

private IPAddress serverIp;//a ch IP ca server


private BackgroundWorker bwServer;//Thread chnh ca server

V Contructor.
public Server()
{
serverIp = Dns.GetHostAddresses(Dns.GetHostName())[0];
listClient = new List<ClientManager>();
}

Bc 12: Ta vit hm chy Server. Ch server chy trn Thread c lp da vo


i tng BackgroundWorker. C 1 s hm private km theo qun l listClient nh
thm, xa cc client khi mt kt ni, login hay logout.
public void Start()
{
bwServer = new BackgroundWorker();
bwServer.DoWork += new DoWorkEventHandler(bwServer_DoWork);
bwServer.RunWorkerAsync();
}
private void bwServer_DoWork(object sender, DoWorkEventArgs e)
{
listenerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream,
ProtocolType.Tcp);
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Any, port);
listenerSocket.Bind(serverEndPoint);
listenerSocket.Listen(200);
while (true)
{
//tao 1 ClientManager mi bt k khi no c kt ni mi
ClientManager newClient = new ClientManager(listenerSocket.Accept());
newClient.CommandReceived += new CommandReceivedEventHandler(newClient_CommandReceived);
newClient.Disconnected += new DisconnectedEventHandler(newClient_Disconnected);
//xa client trong list nu IP ca n c lu trong list
this.RemoveClientManager(newClient.IP);
//thm Client mi vo list
listClient.Add(newClient);
}
}
//Dn dp, xa client trong list nu server mt kt ni vi n v gi clientlist mi
private void newClient_Disconnected(object sender, ClientEventArgs e)
{
ClientManager client = (ClientManager)sender;
listClient.Remove(client);
UserEventArg userEvent = new UserEventArg(client.ClientName);
SendUserOnlineList();
}
private void newClient_CommandReceived(object sender, CommandEventArgs e)
{
ClientManager client = (ClientManager)sender;
Command cmd = e.Command;
switch (cmd.CommandType)
{
// khi ang nhp
case CommandType.Login:
{

//t tn cho Client mi bng tn ng nhp


string name = SetManagerName(cmd.SenderIP, cmd.MetaData);
//kim tra xem tn c trng vi tn c khng
if (!IsNameExists(cmd.SenderIP, name))
{
//nu ko thi gi clientlist mi cho tt c cc my
SendUserOnlineList();
}
else
{
//nu c th gi thng bo l tn c ngi khc dng
Command sendcmd = new Command(CommandType.NameExists, cmd.SenderIP);
sendcmd.SenderIP = serverIp;
sendcmd.SenderName = "server";
client.SendCommand(sendcmd);
}
break;
}
//khi ang xut
case CommandType.Logout:
{
SendUserOnlineList();
break;
}
//forward tin nhn
case CommandType.Message:
{
string targetname = cmd.MetaData.Split(new char[] { '|' })[0];
SendCommandToTarget(targetname, cmd);
break;
}
}
}
//t tn cho Client
private string SetManagerName(IPAddress remoteClientIP, string nameString)
{
int index = this.IndexOfClient(remoteClientIP);
if (index != -1)
{
string name = nameString.Split(new char[] { ':' })[0];
this.listClient[index].ClientName = name;
return name;
}
return "";
}
//Ly v tr ca Client cho a ch l IP trong list
private int IndexOfClient(IPAddress ip)
{
int index = -1;
foreach (ClientManager cMngr in listClient)
{
index++;
if (cMngr.IP.Equals(ip))
return index;
}
return -1;
}
//Xa 1 client c a ch l IP
private bool RemoveClientManager(IPAddress ip)
{
lock (this)
{
int index = this.IndexOfClient(ip);

10

if (index != -1)
{
string name = listClient[index].ClientName;
listClient.RemoveAt(index);
SendUserOnlineList();
return true;
}
return false;
}
}
//kim tra xem tn ng nhp c cha
private bool IsNameExists(IPAddress remoteClientIP, string nameToFind)
{
foreach (ClientManager mngr in this.listClient)
if (mngr.ClientName == nameToFind && !mngr.IP.Equals(remoteClientIP))
return true;
return false;
}

Bc 13: Vit 1 s hm public quan trng iu kin Server.


//gi command cho tt c client trong list
public void BroadCastCommand(Command cmd)
{
foreach (ClientManager mngr in this.listClient)
mngr.SendCommand(cmd);
}
//gi command cho targetname bng cch tm ClientManager trong list
public void SendCommandToTarget(string targetname, Command cmd)
{
foreach (ClientManager mngr in this.listClient)
if (mngr.ClientName.Equals(targetname))
{
cmd.Target = mngr.IP;
mngr.SendCommand(cmd);
return;
}
}
//Gi danh sch client Online cho tt c cc my online trn mng
public void SendUserOnlineList()
{
string userOnline = "";
foreach (ClientManager c in listClient)
{
userOnline += "|" + c.ClientName + ":" + c.IP.ToString();
}
Command cmd = new Command(CommandType.ClientList, this.serverIp, userOnline);
cmd.SenderIP = this.serverIp;
cmd.SenderName = "server";
BroadCastCommand(cmd);
}
//ng Server
public void Stop()
{
foreach (ClientManager c in listClient)
{
c.Disconnect();
}

11

Bc 14: Bc cui cng hon tt 1 server chat n gin. M file frmServer.cs.


V phn giao din form ta c th t do thch v g cng c. Quan trng l x l 2 x
kin chnh cho form l Form_Load v Form_Closing. To 1 i tng Server. Gi
hm Start() Form_Load v hm stop Form_Closing. Ta c th thm nt Start v
Stop ln form.

2. Lp trnh Client:
Bc 1: Tng t bn Server, ta to 1 project mi c tn l UITChatClient dng
Windows Form. Trong cng Solution ta to thm 1 project mi c dng Class
Library tn l ChatClient, ng thi add thm project Command ca Server v client v
server phi ng b v Command. Thm 1 file c tn l EventArgs.cs cho project
ChatClient.
Bc 2: M file EventArgs.cs ca ChatClient v tin hnh nh ngha 1 s
EventArg, delegate cho ChatClient.
//Nhn c Command
public delegate void
//Mt kt ni server
public delegate void
//Kt ni thnh cng
public delegate void
//kt ni b li
public delegate void

CommandReceivedEventHandler(object sender, CommandEventArgs e);


DisconnectedEventHandler(object sender, EventArgs e);
ConnectingSuccessedEventHandler(object sender, EventArgs e);
ConnectingFailedEventHandler(object sender, EventArgs e);

public class CommandEventArgs : EventArgs


{
private Command command;
public Command Command
{
get { return command; }
}
public CommandEventArgs(Command cmd)
{
this.command = cmd;
}
}

Bc 3: M file ChatClient.cs, to 1 class ChatClient v tin hnh ci t cho class


ny.
Trc tin l nh ngha 1 s thuc tnh v Contructor.
private
private
private
private

string username;//tn ng nhp


IPAddress localAddress;//a ch IP ca my hin hnh
IPAddress remoteAddress;//a ch IP ca Server
int port = 1024;//port kt ni vi Server

12

private
private
private
private

BackgroundWorker bwReceiver;//thread nhn command


BackgroundWorker bwConnector;//thread kt ni
NetworkStream networkStream;//Lun ghi,c d liu
Socket clientSocket;

public string UserName


{
get
{
return username;
}
set
{
username = value;
}
}
public IPAddress LocalAddress
{
get
{
return localAddress;
}
}
//Contructor
public ChatClient(string Username)
{
username = Username;
localAddress = Dns.GetHostAddresses(Dns.GetHostName())[0];
}

Bc 4: Vit hm nhn v gi Command cho ChatClient tng t nh bn pha


Server trnh by trn. C th tm tt li nh sau:
Nhn Command, Client cn phi kt ni vi Server, to socket kt ni vi Server ri
mi thc hin nhn Command:
public void ConnectTo(IPAddress address)
{
remoteAddress = address;
bwConnector = new BackgroundWorker();
bwConnector.DoWork += new DoWorkEventHandler(bwConnector_DoWork);
bwConnector.RunWorkerCompleted += new
RunWorkerCompletedEventHandler(bwConnector_RunWorkerCompleted);
bwConnector.RunWorkerAsync();
}
private void bwConnector_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
//kim tra xem kt ni c thnh cng khng v pht ra x kin tng ng
if ((bool)e.Result == false)
OnConnectingFailed(new EventArgs());
else
OnConnectingSuccessed(new EventArgs());
((BackgroundWorker)sender).Dispose();
}
private void bwConnector_DoWork(object sender, DoWorkEventArgs e)

13

try
{

//to socket
this.clientSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
IPEndPoint serverEP = new IPEndPoint(remoteAddress, port);
//kt ni ti IP ca server
this.clientSocket.Connect(serverEP);
e.Result = true;
//to 1 lun nhn v ghi d liu ln socket
this.networkStream = new NetworkStream(this.clientSocket);
//to 1 thread nhn Command
this.bwReceiver = new BackgroundWorker();
this.bwReceiver.WorkerSupportsCancellation = true;
this.bwReceiver.DoWork += new DoWorkEventHandler(Receive);
this.bwReceiver.RunWorkerAsync();
}
catch
{
e.Result = false;//kt ni ko thnh cng
}
}
private void Receive(object sender, DoWorkEventArgs e)
{
Tng t bn pha Server
}

Gi Command:
public void SendCommandToDestination(Command cmd)
{
if (this.clientSocket != null && this.clientSocket.Connected)
{
BackgroundWorker bwSender = new BackgroundWorker();
bwSender.DoWork += new DoWorkEventHandler(bwSender_DoWork);
bwSender.RunWorkerCompleted += new
RunWorkerCompletedEventHandler(bwSender_RunWorkerCompleted);
bwSender.RunWorkerAsync(cmd);
}
}
private void bwSender_DoWork(object sender, DoWorkEventArgs e)
{
Command cmd = (Command)e.Argument;
e.Result = this.SendCommand(cmd);
}
private void bwSender_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
((BackgroundWorker)sender).Dispose();
GC.Collect();
}
System.Threading.Semaphore semaphor = new System.Threading.Semaphore(1, 1);
private bool SendCommand(Command cmd)
{
Tng t nh bn Server
}

14

Bc 5: Thit k form Chat.Chuyn qua project UITChatClient. Reference n 2


project cn li.
To thm 1 form c tn l frmLogin. Thit k form
Login nh hnh v. Ch :
-

Textbox Server IP tn l txtServerIP.


Textbox User Name tn l txtUsername.
Button Login c tn l btnLogin.
Button Cancel c tn l btnCancel.
Vit code cho frmLogin kh n gin nh sau:

private string ipString;//chui IP ca server


private string username;//tn ng nhp
private bool isCancel = true;//kim tra xem c bm Cancel khng
//cc property
public bool IsCancel
{
get
{
return isCancel;
}
}
public string IPString
{
get
{
return ipString;
}
}
public string UserName
{
get
{
return username;
}
}
//contructor
public frmLogin()
{
InitializeComponent();
}
private void btnLogin_Click(object sender, EventArgs e)
{
username = txtUsername.Text.Trim();
ipString = txtServerIP.Text.Trim();
isCancel = false;
this.Close();
}
private void btnCancel_Click(object sender, EventArgs e)
{

15

this.Close();

Bc 6: To form frmChat.
Thit k giao din v t tn nh hnh v.
Form ny c chc nng hin th tn tt c cc
client ang online v c th chat vi bt k client
no bng cch click vo tn client v bm vo
nt chat.
- u tin trnh li Cross-thread ta to 2
delegate cho vic update li list useronline v chn
Message vo form frmInstantChat tng ng.

public delegate void insertMessage(string Targetname,string message);


public delegate void updateUserList(string[] UserName);

V 2 hm tng ng nh sau:
private void InsertMessage(string Targetname, string Message)
{
frmInstantChat IM=null;
//duyt qua tt c cc form ang m
foreach (Form form in Application.OpenForms)
{
//gn cho form thnh frmIntantChat
IM = form as frmInstantChat;
if (IM == null)
continue;
if (IM.TargetName == Targetname)//kim tra targetname ng khi
form chat c m sn
{
break;
}
}
if (IM == null)
{
IM = new frmInstantChat(client.UserName,Targetname, this);
IM.Show();
}
//chn message vo form
IM.InsertMessage(Targetname,Message);
IM.Focus();
}
private void UpdateUserList(string[] UserName)
{
lsbUserOnline.Items.Clear();
foreach (string s in UserName)

16

if (s.Trim()!="" && s!=client.UserName)


lsbUserOnline.Items.Add(s);

- Tip theo ta to 1 i tng ChatClient, trong Form_Load ta s cho hin


frmLogin ly thng tin, khi to i tng ChatClient v kt ni vi Server nh
sau:
formlogin = new frmLogin();
formlogin.ShowDialog();
if (formlogin.IsCancel)
{
this.Close();
return;
}
try
{
//to i tng ChatClient
client = new ChatClient(formlogin.UserName);
//gn cc x kin
client.CommandReceived += new
CommandReceivedEventHandler(client_CommandReceived);
client.ConnectingFailed += new
ConnectingFailedEventHandler(client_ConnectingFailed);
client.Disconnected += new DisconnectedEventHandler(client_Disconnected);
client.ConnectingSuccessed += new
ConnectingSuccessedEventHandler(client_ConnectingSuccessed);
//kt ni vi server
client.ConnectTo(IPAddress.Parse(formlogin.IPString));
}
catch
{
MessageBox.Show("Erro!!!");//bo li nu ip server b sai
Close();
}

Tip theo ta x l cc tnh hung Disconnected, ConnectingSuccessed,


ConnectedFailed nh sau:

private void client_ConnectingSuccessed(object sender, EventArgs e)


{
//gi tn ng nhp cho server v thng bo login
Command cmd = new Command(CommandType.Login, client.RemoteAddress,
formlogin.UserName);
cmd.SenderIP = client.LocalAddress;
cmd.SenderName = client.UserName;
client.SendCommandToDestination(cmd);
}
private void client_Disconnected(object sender, EventArgs e)
{
MessageBox.Show("Disconnected");
this.Close();
}
private void client_ConnectingFailed(object sender, EventArgs e)

17

MessageBox.Show("Connecting failed");
this.Close();

Phn quan trng nht l x l cho tnh hung CommandReceive. i vi mi


loi CommandType ta c cc cch x l khc nhau. Sau y l cch x l cho
3 loi CommandType c bn nht cho chng trnh Chat.

Command cmd = e.Command;


string[] metadata = cmd.MetaData.Split(new char[] { '|' });
switch (cmd.CommandType)
{
case CommandType.ClientList:
{
//Cp nht li ClientList
if (!this.InvokeRequired)
this.Invoke(new updateUserList(UpdateUserList),new
object[]{metadata});
break;
}
case CommandType.Message:
{
int t = cmd.MetaData.IndexOf('|');
string message = cmd.MetaData.Substring(t+1);
string name = cmd.SenderName;
//gi hm InserMessage thng qua delegate
this.Invoke(new insertMessage(InsertMessage), new object[] {
name, message });
break;
}
case CommandType.NameExists:
{
//nu tn tn ti ri th s yu cu nhp li tn khc
MessageBox.Show("Name is Exist");
formlogin = new frmLogin();
formlogin.ShowDialog();
client.UserName = formlogin.UserName;
Command logincmd = new Command(CommandType.Login,
client.RemoteAddress, client.UserName);
logincmd.SenderIP = client.LocalAddress;
logincmd.SenderName = client.UserName;
client.SendCommandToDestination(logincmd);
break;
}
}

Cui cng ta gi hm client.Disconnect() trong hm Form_Closing

18

Bc 7: To thm 1 form c tn l frmInstantChat.Giao din v cch t tn


tng t nh hnh v. Form ny
cn c cc thuc tnh l
UserName (tn ngi dng),
TargetName(tn bn chat),
MainForm(form chnh) v 1
hm public InsertMessage dng
chn thm 1 message vo
RichTextBox v c th gi t
form khc.
Cch vit code nh sau:

private string targetname;


private string username;
private frmClient mainform;
public string TargetName
{
get
{
return targetname;
}
}
public frmInstantChat(string Username,string Targetname,frmClient
Client)
{
InitializeComponent();
targetname = Targetname;
username = Username;
mainform = Client;
}
//hm chn 1 chui vo RichTextBox
public void InsertMessage(string name, string Message)
{
rtbOutPut.AppendText(name + ":" + Message);
rtbOutPut.AppendText(Environment.NewLine);
}
private void btnSend_Click(object sender, EventArgs e)
{
if (txtInput.Text.Trim() != "")
mainform.sendMessage(targetname, txtInput.Text.Trim());
InsertMessage(username, txtInput.Text);
txtInput.Text = "";

19

III. Kt lun:
-

lm 1 chng trnh chat theo m hnh Client-Server kh n gin.


Theo m hnh ny rt c li cho vic nng cp cc tnh nng cao cp hn nh
Send File, Share Photo, chi game.
Nhng giao tip di dng thng ip nh mun gi gia 2 my vi m hnh
ny ch cn cp nhp thm CommandType v x l CommandType ny sau
khi nhn xong l c.

Mong nhn c s gp ca bn.


Mi thc mc hay gp xin vui lng
mail v a ch: namlh@escuit.com

20

You might also like