huong dan lam chuong trinh chat

20
1 Đại Học Quốc Gia Thành Phố Hồ Chí Minh Trường Đại học Công nghệ Thông tin Lớp K2C6 Hướng dẫn chi tiết làm 1 chương trình Chat đơn giản Giáo viên hướng dẫn: Phạm Thi Vương I. Giới thiệu chung về cấu trúc. - Chat theo mô hình Client-Server, sử dụng giao thức TCP. - Đơn vị truyền thông tin là Command. - Sử dụng các namespace chính là: o System.Net; o System.Net.Sockets; o System.CompomentModel; II. Hướng dẫn chi tiết: 1. Lập trình Server: Bước 1 : vào Visual C# tạo 1 project mới có tên là UITChatServer, có dạng là Windows Form. Đặt tên cho class chính là frmServer. Tiếp tục trên Solution hiện tại tạo thêm 2 project có dạng Class Library đặt tên là Command và Server . Bước 2 : vào project Command tạo 2 file có tên là Enum.cs và Command.cs. Bước 3 : mở file Enum.cs nhập vào đoạn code sau đây để định nghĩa các loại command sẽ dùng, khi muốn update thì cần chú ý nội dụng của file này. public enum CommandType { Message,// Để gửi message ClientList,//Để gửi danh sách client online NameExists,// thông báo tên vừa đăng nhập đã có người sử dụng Login, //thông báo đăng nhập Logout,//thông báo đăng xuất } Bươc 4 : Mở file Command.cs và nhập vào đoạn code sau dùng định nghĩa 1 đối tượng command dùng để truyền trên mạng, gồm có CommandType, SenderName, SenderIP, TargerIP, using System.Net; namespace UITChat

Upload: xmenhoangtu2

Post on 18-Nov-2014

1.794 views

Category:

Documents


1 download

TRANSCRIPT

i Hc Quc Gia Thnh Ph H Ch MinhTrng i hc Cng ngh Thng tin

Lp K2C6

Hng dn chi tit lm 1 chng trnh Chat n ginGio 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

1

{

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

2

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 {

3

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();

4

} #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);

5

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();

6

}

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();

7

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 listClient;//danh sach cc client online private Socket listenerSocket;//socket nghe cc kt ni mi private int port = 1024;//port c nh nhn Command

8

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(); }

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: {

9

//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: [email protected]

20