這裡需要注意的就是上面的偵聽端口,是程序接收消息時的偵聽端口,也就是IMessageReceiver所使用的。其他的沒有什麼好說的,下來我 們直接看一下代碼,控件的命名是自解釋的,我就不多說什麼了。唯一要稍微說明下的是txtMessage指的是下面發送消息的文本框, txtContent指上面的消息記錄文本框:
public partial class PrimaryForm : Form {
private Talker talker;
private string userName;
public PrimaryForm(string name) {
InitializeComponent();
userName = lbName.Text = name;
this.talker = new Talker();
this.Text = userName + " Talking ...";
talker.ClIEntLost +=
new ConnectionLostEventHandler(talker_ClIEntLost);
talker.ClIEntConnected +=
new ClientConnectedEventHandler(talker_ClIEntConnected);
talker.MessageReceived +=
new MessageReceivedEventHandler(talker_MessageReceived);
talker.PortNumberReady +=
new PortNumberReadyEventHandler(PrimaryForm_PortNumberReady);
}
void ConnectStatus() { }
void DisconnectStatus() { }
// 端口號OK
void PrimaryForm_PortNumberReady(int portNumber) {
PortNumberReadyEventHandler del = delegate(int port) {
lbPort.Text = port.ToString();
};
lbPort.Invoke(del, portNumber);
}
// 接收到消息
void talker_MessageReceived(string msg) {
MessageReceivedEventHandler del = delegate(string m) {
txtContent.Text += m;
};
txtContent.Invoke(del, msg);
}
// 有客戶端連接到本機
void talker_ClIEntConnected(IPEndPoint endPoint) {
ClIEntConnectedEventHandler del = delegate(IPEndPoint end) {
IPHostEntry host = Dns.GetHostEntry(end.Address);
txtContent.Text +=
String.Format("System[{0}]:\r\n遠程主機{1}連接至本地。\r\n", DateTime.Now, end);
};
txtContent.Invoke(del, endPoint);
}
// 客戶端連接斷開
void talker_ClIEntLost(string info) {
ConnectionLostEventHandler del = delegate(string information) {
txtContent.Text +=
String.Format("System[{0}]:\r\n{1}\r\n", DateTime.Now, information);
};
txtContent.Invoke(del, info);
}
// 發送消息
private void btnSend_Click(object sender, EventArgs e) {
if (String.IsNullOrEmpty(txtMessage.Text)) {
MessageBox.Show("請輸入內容!");
txtMessage.Clear();
txtMessage.Focus();
return;
}
Message msg = new Message(userName, txtMessage.Text);
if (talker.SendMessage(msg)) {
txtContent.Text += msg.ToString();
txtMessage.Clear();
} else {
txtContent.Text +=
String.Format("System[{0}]:\r\n遠程主機已斷開連接\r\n", DateTime.Now);
DisconnectStatus();
}
}
// 點擊連接
private void btnConnect_Click(object sender, EventArgs e) {
string host = txtHost.Text;
string ip = txtHost.Text;
int port;
if (String.IsNullOrEmpty(txtHost.Text)) {
MessageBox.Show("主機名稱或地址不能為空");
}
try{
port = Convert.ToInt32(txtPort.Text);
}catch{
MessageBox.Show("端口號不能為空,且必須為數字");
return;
}
if (talker.ConnectByHost(host, port)) {
ConnectStatus();
txtContent.Text +=
String.Format("System[{0}]:\r\n已成功連接至遠程\r\n", DateTime.Now);
return;
}
if(talker.ConnectByIp(ip, port)){
ConnectStatus();
txtContent.Text +=
String.Format("System[{0}]:\r\n已成功連接至遠程\r\n", DateTime.Now);
}else{
MessageBox.Show("遠程主機不存在,或者拒絕連接!");
}
txtMessage.Focus();
}
// 關閉按鈕點按
private void btnClose_Click(object sender, EventArgs e) {
try {
talker.Dispose();
Application.Exit();
} catch {
}
}
// 直接點擊右上角的叉
private void PrimaryForm_FormClosing(object sender, FormClosingEventArgs e) {
try {
talker.Dispose();
Application.Exit();
} catch {
}
}
// 點擊注銷
private void btnSignout_Click(object sender, EventArgs e) {
talker.SignOut();
DisconnectStatus();
txtContent.Text +=
String.Format("System[{0}]:\r\n已經注銷\r\n",DateTime.Now);
}
private void btnClear_Click(object sender, EventArgs e) {
txtContent.Clear();
}
}
在上面代碼中,分別通過四個方法訂閱了四個事件,以實現自動通知的機制。最後需要注意的就是SignOut()和Dispose()的區分。SignOut ()只是斷開連接,Dispose()則是離開應用程序。
總結
這篇文章簡單地分析、設計及實現了一個聊天程序。這個程序只是對無服務器模式實現聊天的一個嘗試。我們分析了需求,隨後編寫了幾個 用例,並對本地、遠程的概念做了定義,接著編寫了程序接口並最終實現了它。這個程序還有很嚴重的不足:它無法實現自動上線通知,而必 須要事先知道端口號並進行手動連接。為了實現一個功能強大且開發容易的程序,更好的辦法是使用集中型服務器模式。
感謝閱讀,希望這篇文章能對你有所幫助。