网络编程文档.docx
- 文档编号:29408061
- 上传时间:2023-07-23
- 格式:DOCX
- 页数:23
- 大小:163.79KB
网络编程文档.docx
《网络编程文档.docx》由会员分享,可在线阅读,更多相关《网络编程文档.docx(23页珍藏版)》请在冰豆网上搜索。
网络编程文档
网络应用编程文档
项目名称:
简单的聊天软件
姓名:
学号:
(下载源码就到新兴网络:
www.NewX)
2009年4月26日
目录
一.需求分析3
1.1开发背景3
1.2功能要求3
1.3运行环境3
1.4功能实现4
二.项目设计5
2.1程序流图5
2.2概要设计6
2.3功能设计6
2.4详细设计8
2.4.1界面设计8
客户端9
2.4.2程序结构设计10
3.1、客户端10
3.2服务器端16
四项目测试18
五、总结:
18
一.需求分析
1.1开发背景
在网络越来越发达的今天,人们对网络的依赖越来越多,越来越离不开网络,由此而产生的聊天工具越来越多,类似QQ、网络聊天时一类的聊天系统的发展日新月异。
但是,QQ等现有的聊天程序也存在着很大的问题。
比如,我在使用QQ的时候,就对他发的各种“广告”深恶痛绝。
对于登陆后时不时弹出的打扰窗口,很是厌烦。
因此我在本次作业的激励下,产生了一个制作类似QQ的网络聊天工具并且“无垃圾信息”洁净聊天工具的想法,而且希望通过制作该程序还能更好的学习网络软件编程知识。
1.2功能要求
(1)登录功能。
(2)客户可以通过服务器转发,实现一对一、一对多和多对多聊天。
(3)实现抖动和声音提醒。
(4)服务器端和客户端程序都能实时显示在线用户数目。
(5)应该具有友好、易用、美观的图形界面。
(6)无垃圾打扰信息
(7)保存和删除聊天信息。
1.3运行环境
本系统基于WINDOWSsocket接口设计,适用于WINDOWSXP等系统。
1.4功能实现
1.登录验证功能。
对于账号重复等异常,需要提示给用户。
2.客户通过服务器转发,实现一对一、一对多和多对多聊天。
3.实时显示目前其它用户的状态,能够提示在线用户数目、状态等。
4.保存并能察看聊天纪录。
5.申请新的用户号码。
6.易用、美观的图形界面,实现系统托盘。
7.收到信息时,能够收到声音等提示信息,发送端还能通过发送抖动,提示聊天的对方。
二.项目设计
2.1程序流图
2.2概要设计
通过C#,实现网络聊天的功能,采用WindowsSocket编程,服务器与客户端采用了TCP/IP连接方式,在设计聊天方案时,实行将所有信息发往服务器端,再由服务器进行分别处理的思路,服务器端是所有信息的中心。
由于服务器端要保存用户信息,我们利用数据库来实现这一功能,因此首先需要建立用户信息数据库。
在客户端保存聊天纪录和用户号码这一功能的实现中,采用了文件系统设计。
在信息到来及好友上线时,通过闪动托盘图标和播放不同的音乐进行提示。
建立消息链表来保存用户接收的各种消息。
2.3功能设计
客户端:
1)登陆功能:
建立与服务器的连接并登陆,能显示登陆错误信息。
2)界面显示:
将在线好友显示在好友列表中,并实现系统托盘,加入工具栏便于操作。
3)聊天功能:
与好友聊天。
4)聊天纪录:
能保存聊天纪录,并能察看聊天纪录。
5)信息提示:
闪动托盘图标提示到来信息,并播放不同音乐来提示。
6)发送窗口抖动,发送端提示聊天的对方。
服务器端:
向各个客户端发布系统消息。
接受来自客户端的各种信息并分别处理。
1)登陆信息:
检查登陆信息是否正确,并向客户端返回登陆信息,如信息正确。
就将在线用户发给该用户,并将该用户的状态发给各在线用户。
同时在服务器端显示出来。
2)聊天信息:
转发给消息指定的用户。
3)申请信息:
自动分配8位用户号码,并保存该用户,同时将信息返回给客户端。
4)用户下线:
将此用户下线消息发给各客户端,并改写用户在服务器端的状态。
程序中主要变量及函数的功能说明如下:
客户端:
privatevoidlogin_btn_Click(objectsender,EventArgse)---登陆到服务器
privatevoidsvrip_tb_TextChanged(objectsender,EventArgse)设置要连接的服务器的地址端口
privatevoidchatrcd_rtb_TextChanged(objectsender,EventArgse)--显示好友发送的信息
privatevoidsend_btn_Click(objectsender,EventArgse)----给好友发送信息
privatevoiduser_tb_TextChanged(objectsender,EventArgse)-----申请新的用户
privatevoidchatrcd_rtb_TextChanged(objectsender,EventArgse)----显示服务器消息
privatevoidmsg_tb_TextChanged(objectsender,EventArgse)-----显示消息输入文本
privatevoidnudge_pb_Click(objectsender,EventArgse)------发送窗口抖动
privatevoidbroadcast_rb_CheckedChanged(objectsender,EventArgse)------聊天模式的变更
privatevoidhide_cb_CheckedChanged(objectsender,EventArgse)-------最小化到托盘
服务器端:
用户及发送信息结构体类型:
publicvoidStartUp()-------服务器启动,并且实时更新用户在线信息
publicvoidGetConfig()------配置服务器端口号等信息
privatevoidThreadFunc(objectobj)-----系统对于发送消息、发送抖动等的异常的处理
publicvoidClose()--------关闭服务器
2.4详细设计
2.4.1界面设计
客户端
1)登陆界面
2)显示当前状态
3)最小化到托盘
4)发送抖动
5)聊天模式变更
6)发送接收消息
客户端
1)服务器启动配置端口号
2)实时更新在线用户信息
2.4.2程序结构设计
如概要设计反映。
三.编码实现
3.1、客户端
a)登陆
privatevoidlogin_btn_Click(objectsender,EventArgse)
{
//验证数据合法性
if(!
ValidateInfo())
{
return;
}
intport=int.Parse(svrport_tb.Text);
//向服务器发出连接请求
TCPConnectionconn=newTCPConnection(_ipAddr,port);
TcpClient_tcpc=conn.Connect();
if(_tcpc==null)
{
MessageBox.Show("无法连接到服务器,请重试!
",
"错误",
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation);
}
else
{
NetworkStreamnetstream=_tcpc.GetStream();
//向服务器发送用户名以确认身份
netstream.Write(Encoding.Unicode.GetBytes(user_tb.Text),0,Encoding.Unicode.GetBytes(user_tb.Text).Length);
//得到登录结果
byte[]buffer=newbyte[50];
netstream.Read(buffer,0,buffer.Length);
stringconnResult=Encoding.Unicode.GetString(buffer).TrimEnd('\0');
if(connResult.Equals("cmd:
:
Failed"))
{
MessageBox.Show("您的用户名已经被使用,请尝试其他用户名!
",
"提示",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
return;
}
else
{
stringsvrskt=svrip_tb.Text+":
"+svrport_tb.Text;
chat_frmchatFrm=newchat_frm(user_tb.Text,netstream,svrskt);
chatFrm.Owner=this;
this.Hide();
chatFrm.Show();
}
}
}
b)发送消息
privatevoidsend_btn_Click(objectsender,EventArgse)
{
stringlocalTxt=null;
stringsendTxt=null;
stringmsg=msg_tb.Text.Trim();
if(msg==string.Empty)
{
MessageBox.Show("不能发送空消息",
"提示",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
return;
}
//如果是聊天室模式则向服务器发送广播请求
if(broadcast_rb.Checked)
{
localTxt=string.Format("[广播]您在{0}对所有人说:
\r\n{1}\r\n\r\n",DateTime.Now,msg);
sendTxt=string.Format("[广播]{0}在{1}对所有人说:
\r\n{2}\r\n\r\n",_username,DateTime.Now,msg);
//发送广播请求
_nws.Write(newbyte[]{0,5},0,2);
}
else
{
string_receiver=online_cb.Text;
if(_receiver==string.Empty)
{
MessageBox.Show("请选择一个接收者!
\n如果没有接受者可选,表明当前只有您一个人在线\t",
"发送消息",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
return;
}
localTxt=string.Format("[私聊]您在{0}对{1}说:
\r\n{2}\r\n\r\n",DateTime.Now,_receiver,msg);
sendTxt=string.Format("[私聊]{0}在{1}对您说:
\r\n{2}\r\n\r\n",_username,DateTime.Now,msg);
//发送接受者用户名
_nws.Write(Encoding.Unicode.GetBytes(_receiver),0,Encoding.Unicode.GetBytes(_receiver).Length);
}
_nws.Write(Encoding.Unicode.GetBytes(sendTxt),0,Encoding.Unicode.GetBytes(sendTxt).Length);
chatrcd_rtb.AppendText(localTxt);
msg_tb.Clear();
}
///
///有新消息来时闪烁任务栏并且保持聊天记录内容滚动到最底端,QQ就是这么玩滴~
///
///
///
[DllImport("user32.dll")]
publicstaticexternboolFlashWindow(IntPtrhWnd,boolbInvert);
privatevoidchatrcd_rtb_TextChanged(objectsender,EventArgse)
{
chatrcd_rtb.ScrollToCaret();
if(this.WindowState==FormWindowState.Minimized)
{
FlashWindow(this.Handle,true);
}
}
///
///当窗口恢复后取消任务栏的闪烁效果
///当窗口最小化时判断是否要隐藏到系统托盘
///
///
///
privatevoidchat_frm_SizeChanged(objectsender,EventArgse)
{
switch(this.WindowState)
{
caseFormWindowState.Normal:
FlashWindow(this.Handle,false);
break;
caseFormWindowState.Minimized:
if(_hideFlag)
{
notifyIcon1.Visible=true;
this.Visible=false;
}
break;
default:
break;
}
}
///
///在线列表下拉框显示之前向服务器发送请求在线列表的命令
///
///
///
privatevoidonline_cb_DropDown(objectsender,EventArgse)
{
_nws.Write(newbyte[]{0,2},0,2);
}
///
///聊天模式改变
///
///
///
privatevoidbroadcast_rb_CheckedChanged(objectsender,EventArgse)
{
if(private_rb.Checked)
{
online_cb.Enabled=true;
}
else
{
online_cb.Enabled=false;
}
}
///
///设置最小化到系统托盘的标记值
///
///
///
privatevoidhide_cb_CheckedChanged(objectsender,EventArgse)
{
_hideFlag=hide_cb.Checked;
}
///
///产生闪屏振动效果
///
privatevoidNudge()
{
if(notifyIcon1.Visible==true)
{
return;
}
if(this.WindowState==FormWindowState.Minimized)
{
this.WindowState=FormWindowState.Normal;
}
inti=0;
Point_old=this.Location;
Point_new1=newPoint(_old.X+2,_old.Y+2);
Point_new2=newPoint(_old.X-2,_old.Y-2);
_sp2.Play();
while(i<4)
{
this.Location=_new1;
Thread.Sleep(60);
this.Location=_new2;
Thread.Sleep(60);
i++;
}
this.Location=_old;
}
c)发送抖动
privatevoidnudge_pb_Click(objectsender,EventArgse)
{
stringdisplayTxt=null;
if(private_rb.Checked&&online_cb.Text==string.Empty)
{
MessageBox.Show("非聊天室模式下必须先选择一个接收者!
",
"发送闪屏振动",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
return;
}
if(private_rb.Checked)
{
_nws.Write(newbyte[]{0,4},0,2);
string_receiver=online_cb.Text;
_nws.Write(Encoding.Unicode.GetBytes(_receiver),0,Encoding.Unicode.GetBytes(_receiver).Length);
displayTxt=string.Format("[系统提示]您向{0}发送了一个闪屏振动。
\r\n\r\n",_receiver);
}
else
{
_nws.Write(newbyte[]{0,3},0,2);
displayTxt="[系统提示]您向所有人发送了一个闪屏振动。
\r\n\r\n";
}
chatrcd_rtb.AppendText(displayTxt);
Nudge();
}
d)关闭,断开连结
privatevoidclose_btn_Click(objectsender,EventArgse)
{
DialogResultret;
ret=MessageBox.Show("确定与服务器断开连接吗?
",
"退出",
MessageBoxButtons.OKCancel,
MessageBoxIcon.Question,
MessageBoxDefaultButton.Button2);
if(ret==DialogResult.OK)
{
//向服务器发送离线请求
_nws.Write(newbyte[]{0,1},0,2);
//结束接受消息的线程
if(_receiveThread!
=null)
{
_receiveThread.Abort();
}
//关闭网络流
_nws.Close();
//关闭父窗口及自身
this.Owner.Close();
this.Close();
}
}
3.2服务器端
1)配置端口号
publicvoidGetConfig()
{
stringportParam;
Console.Write("请输入监听端口,直接回车则接受默认端口8888:
");
portParam=Console.ReadLine();
if(portParam!
=string.Empty)
{
if(!
int.TryParse(portParam,out_port)||_port<1023||_port>65535)
{
_port=8888;
Console.WriteLine("端口号不合法,默认端口号被接受!
");
}
}
}
2)启动服务器,监听客户端状态,实时变更
publicvoidStartUp()
{
IPAddress_ip=Dns.GetHostAddresses(Dns.GetHostName())[0];
_tcpl=newTcpListener(_ip,_port);
_tcpl.Start();
Console.WriteLine("服务器已启动,正在监听...\n");
Console.WriteLine(string.Format("服务器IP:
{0}\t端口号:
{1}\n",_ip,_port));
while(true)
{
byte[]packetBuff=newbyte[_maxPacket];
SocketnewClient=_tcpl.AcceptSocket();
newClient.Receive(packetBuff);
stringuserName=Encoding.Unicode.GetString(packetBuff).TrimEnd('\0');
//验证是否为唯一用户
if(_transmit_tb.Count!
=0&&_transmit_tb.ContainsKey(userName))
{
newClient.Send(Encoding.Unicode.GetBytes("cmd:
:
Failed"));
continue;
}
else
{
newClient.Send(Encoding.Unicode.GetBytes("cmd:
:
Successful"));
}
//将新连接加入转发表并创建线程为其服务
_transmit_tb.Add(userName,newClient);
stringsvrlog=string.Format("[系统消息]新用户{0}在{1}已连接...当前在线人数:
{2}\r\n\r\n",userName,DateTime.Now,_transmit_tb.Count);
Console.WriteLine(svrlog);
ThreadclientThread=newThread(newParameteri
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 网络 编程 文档