d.搜索好友界面:在主界面中的搜索框内输入要搜索的好友名,点击搜索按钮,就可直接跳转到好友搜索的界面,并在界面显示出搜索的结果。若想直接添加为好友,直接单击好友头像即可添加并返回好友列表界面(此时已加入新好友)。若是想另外搜索好友,可在搜索文本框里输入要搜索的好友名,单击搜索即可。
e.好友聊天界面:进入好友聊天界面,直接在下面的文本框内输入想要与好友发送的内容,点击发送即可将消息发送给对方,要求双方同时在线聊天。
8
(6) 数据库设计
本程序示通过用ADO来访问数据库,分别用ADO访问了数据库的各个对象及各方法。
数据库主要包括两个表:一个用来存储好友信息;一个用来存储用户信息。数据库还要根据客户端的操作及时更新表的内容。
表UserInfo:用来存储已注册用户的帐号信息。主要包括昵称、密码、头像、性别、年龄等信息的。
表Friends:用来存储我的好友信息。
Friends和UserInfo表的关系:
9
4 源代码
(1)服务器端
a.主界面:
//点击启动按钮的响应函数
privatevoid btnStart_Click(object sender, EventArgs e) {
//Start listening if (IsStart) return;
IPAddress ip = IPAddress.Any; //提供一个 IP 地址,指示服务器应侦听所有网络接口上的客户端活动
IPEndPoint localep = newIPEndPoint(Dns.Resolve(Dns.GetHostName()).AddressList[0], 11000);
10
listener = newTcpListener(localep); listener.Start(10); IsStart = true;
lstBox1.Invoke(AppendString, string.Format(\服务器启动侦听!端点为:{0}\,
listener.LocalEndpoint.ToString()));
ClientSocket = newSocket[256]; //接受连接请求的异步调用
AsyncCallback callback = newAsyncCallback(AcceptCallback); listener.BeginAcceptSocket(callback, listener); btnStart.Enabled = false; }
//异步接收来自客户端的消息
privatevoid AcceptCallback(IAsyncResult ar) { try {
//完成异步接受连接的请求的异步调用 //将接收信息添加到列表中
Socket handle = listener.EndAcceptSocket(ar); MyFriend frd = newMyFriend(handle); //保存为此客户建立的连接
ClientSocket[ClientNum++] = handle; lstBoxStatu.Invoke(Addfriend, frd); AsyncCallback callback; //继续调用异步方法接受连接请求 if (IsStart) {
callback = newAsyncCallback(AcceptCallback); listener.BeginAcceptSocket(callback, listener); }
//开始在异步连接上进行异步的数据接收 frd.ClearBuffer();
callback = newAsyncCallback(ReceiveCallback);
frd.socket.BeginReceive(frd.Rcvbuffer, 0, frd.Rcvbuffer.Length, SocketFlags.None, callback, frd); } catch {
IsStart = false; } }
//对接收到的消息进行处理
privatevoid ReceiveCallback(IAsyncResult ar) {
11
MyFriend frd = (MyFriend)ar.AsyncState; try {
int i = frd.socket.EndReceive(ar); if (i == 0) {
lstBoxStatu.Invoke(Removefriend, frd); return; } else {
ClassMessage msg = newClassMessage(); msg =
(ClassMessage)newClassSerializers().DeSerializeBinary(newMemoryStream(frd.Rcvbuffer));
string data = string.Format(\:{0}\, frd.socket.RemoteEndPoint.ToString()); lstBoxStatu.Invoke(AppendString, data); //响应客户端请求
Respond(frd, msg); frd.ClearBuffer();
AsyncCallback callback = newAsyncCallback(ReceiveCallback);
frd.socket.BeginReceive(frd.Rcvbuffer, 0, frd.Rcvbuffer.Length, SocketFlags.None, callback, frd); } } catch {
lstBoxStatu.Invoke(Removefriend, frd); } }
//服务器对客户端消息的响应函数
privatevoid Respond(MyFriend frd, ClassMessage msg) {
//根据接收信息给出响应 switch (msg.msgCommand) {
caseMsgCommand.Logining: Data LoginSQL = newData(); LoginMsg log_msg =
(LoginMsg)newClassSerializers().DeSerializeBinary(newMemoryStream(msg.Data)); if (LoginSQL.LoginExSQL(log_msg, frd.socket.RemoteEndPoint.ToString()) == 1) {
msg.msgCommand = MsgCommand.Logined; }
12