7-3-4 编写聊天程序
聊天程序有很多,比如QQ,MSN等。聊天程序的发展从一开始的传送文字信息到传送文件,语音、图像不断升级,从本质上说都是使用相同协议传送数据,只不过数据格式有所不同。投入应用的聊天软件同时在线聊天的人数较多,发送消息需分辨接收者,同时确定消息边界。
1. 案例学习:聊天程序
u
实验步骤(1):
创建服务端控制台应用程序ChatServer。先启动服务,在服务器端开始监听,接收从客户端的连接请求建立连接,并显示当前在线人数。
u
实验步骤(2):
运行启动服务器,显示服务器地址和端口,监听来自客户端的连接,修改源代码:
HashTable clientTable = new HashTable();
IPAddress ip = Dns.GetHostAddresses(Dns.GetHostName())[0];
TcpListener listener = new TcpListener(ip, port);
listener.Start();
Console.WriteLine("
服务器已启动,正在监听...\n");
Console.WriteLine(string.Format("
服务器IP:{0}\t端口号:{1}\n", ip, port));
while (true)
{
byte[] packetBuff = new byte[maxSize];
Socket newClient = listener.AcceptSocket();
newClient.Receive(packetBuff);
string userName = Encoding.Unicode.GetString(packetBuff).TrimEnd('\0');
//
验证是否为唯一用户
if (clientTable.Count != 0 && clientTable.ContainsKey(userName))
{
newClient.Send(Encoding.Unicode.GetBytes("Failed"));
continue;
}
else
{
newClient.Send(Encoding.Unicode.GetBytes("Successful"));
}
//
将新连接加入转发表并创建线程为其服务
clientTable.Add(userName, newClient);
string strlog = string.Format("[
系统消息]新用户 {0} 在 {1} 已连接... 当前在线人数: {2}\r\n\r\n", userName, DateTime.Now, clientTable.Count);
Console.WriteLine(strlog);
Thread th = new Thread(new ParameterizedThreadStart(ThreadFunc));
th.Start(userName);
//
向所有客户机发送系统消息
foreach (DictionaryEntry de in clientTable)
{
string clientName = de.Key as string;
Socket clientSkt = de.Value as Socket;
if (!clientName.Equals(userName))
{
clientSkt.Send(Encoding.Unicode.GetBytes(strlog));
}
}
}
u
实验步骤(3):
创建客户端应用程序ChatClient,添加文本框和按钮,界面布局同前面的例子类似,不同的是可以选择接收者即所谓的“私聊”。
u
实验步骤(4):
至少同时打开两个客户端连接服务器,添加代码:
string msg = txtMsg.Text.Trim();
string strSend = null;
string strReceiver = txtReceiver.Text;
if (strReceiver == string.Empty)
{
MessageBox.Show("
请选择一个接收者!\n如果没有接受者可选,表明当前只有您一个人在线\t",
"
发送消息",MessageBoxButtons.OK,MessageBoxIcon.Information);
return;
}
strLocal = string.Format("
您在 {0} 对 {1} 说:\r\n{2}\r\n ", DateTime.Now, strReceiver, msg);
strSend = string.Format("{0}
在 {1} 对您说:\r\n{2}\r\n ", username, DateTime.Now, msg);
//
发送接受者用户名
netstream.Write(Encoding.Unicode.GetBytes(strReceiver), 0, Encoding.Default.GetBytes(strReceiver).Length);
}
netstream.Write(Encoding.Unicode.GetBytes(strSend), 0, Encoding.Default.GetBytes(strSend).Length);
rtbChat.AppendText(strLocal);
txtMsg.Clear();
这里指定聊天对象,将对方的用户名同发送的信息一起写入网络流,接收时需取出用户名,发送指定信息。
问题讨论:
发送信息时将用户名写入网络流,接收时如何取出?
u
实验步骤(5):
发送广播信息,即对所有用户发送信息,不区分接收者,添加代码:
String msg=txtMsg.Text.Trim();
if (rbBroadcast.Checked)
{
strLocal = string.Format("[
广播]您在 {0} 对所有人说:\r\n{1}\r\n ", DateTime.Now, msg);
strSend = string.Format("[
广播]{0} 在 {1} 对所有人说:\r\n{2}\r\n ", username, DateTime.Now, msg);
//
发送广播请求
netstream.Write(new byte[] { 0, 5 }, 0, 2);
}
netstream.Write(Encoding.Unicode.GetBytes(strSend), 0, Encoding.Unicode.GetBytes(strSend).Length);
rtbChat.AppendText(strLocal);
txtMsg.Clear();
比较发送广播消息和指定用户消息的不同。
7-4 本章小结
n
.NET Framework对于网络编程的支持。
n
主要Http网络编程类。
n
主要Tcp网络编程类。
n
使用协议通信的基本方法。
课 后 练 习
1、
使用DNS类和IPHostEntry类创建一个域名解析器。用户输入主机名或者DNS域名以后,能在下面的列表框中显示与主机或者DNS域名对应的IP地址和别名。
要求:
(1)
添加两个文本框用于输入主机名或者IP地址。
(2)
列表框用于显示与输入相对应的地址或别名。
2、
编写一个聊天软件,添加自定义表情,添加好友列表等
要求:可以传输文件
3、
试使用Tcp相关类编写一个网络五子棋游戏。
本文转自 qianshao 51CTO博客,原文链接:http://blog.51cto.com/qianshao/231846,如需转载请自行联系原作者