计算机网络课程设计报告
----基于UDP的即时通信工具的设计开发
学院:
一、课设任务
任务一,设计一个基于UDP的点对点通信工具,实现点对点的通信,如下图所示,用户发送的信息将在对方用户中显示,显示内容包括用户名+发送时间+发送内容。
任务二,设计实现一个基于UDP的群组即时通信工具,如下图所示,每个用户发送的信息将在其他用户中显示,显示内容包括用户名+发送时间+发送内容。
二、课设内容
用户数据报(UDP)是一个无连接协议,使用这种协议时,并不需要在两台计算机之间建立固定的连接,也就是说,通信双方没有服务器和客户机之分,它们之间进行的是对等通信,所以它的优势很明显,是现代通信不可或缺的一部分。所以,利用它的优势设计一个可以实现私聊和群聊的软件,实现两台计算机间的即时通讯。
三、课设目的
(1) 熟练掌握C#语言的编程技术、步骤,程序的编写与调试过程
(2) 理解UDP协议的基本功能和工作原理
(3) 培养运用理论知识解决实际问题的能力
(4) 理解UDP协议在C#编程语言中的体现
四、课程设计要求
基于UDP协议实现一对一的聊天和一对多的聊天,提供友好的用户界面,便于用户进行操作。
根据目前使用聊天程序的用户需求显示,用户对于聊天程序主要有以下几点要求:
(1)聊天功能:可以实现实时接收和发送文字信息,并能支持公聊和私聊的方式。
(2)用户功能:可以查看对方的开放信息,以及发送方的IP。
五、任务解决
客户机/服务器模式
由于这次课程设计是实现点到点的可靠连接,所以在此使用UDP连接方式。
在这个连接中,双方分为客户和服务器,他们各自的功能不同。
客户机一方,UDP应用程序功能如下:
(1)打开通信信道(申请一套接字),并连接到服务器在主机的保留端口,该端口对应服务器的UDP进程。
(2)向服务器发出请求报文,等待接收应答。
(3)从服务器方收到最终应答结果,或在不再请求时关闭信道并终止客户机进程。
服务器一方,UDP应用程序动作如下:
(1)打开通信信道(申请一套接字),通知本地主机在某一保留端口接收客户机请求。
(2)等待客户请求到达指定端口。
(3)接收到请求,启动一新进程处理用户请求,同时释放旧进程以响应新的客户请求,一旦服务完成,关闭新进程与客户的通信链路。
(4)继续等待客户机请求。
(5)如果不想响应客户机请求,关闭服务器进程。
六、功能模块调用流程
七、程序清单
(1)点对点
using System;//指明程序可能需要使用的类
using System.Collections.Generic;//指明程序可能需要使用的类
using System.ComponentModel;//指明程序可能需要使用的类
using System.Data;//指明程序可能需要使用的类
using System.Drawing;//指明程序可能需要使用的类
using System.Linq;
using System.Text;//指明程序可能需要使用的类
using System.Threading.Tasks;
using System.Windows.Forms;//指明程序可能需要使用的类
using System.Net;
using System.Threading;
using System.Net.Sockets;
namespace 点对点//指明项目名称
{
public partial class UDP点对点 : Form//生产窗体类
{
UdpClient myudp;
UdpClient udp;
private IPAddress localaddressip;
private IPAddress sendremoteip;
private const int port = 8889;
public UDP点对点()//窗体呈现时调用的函数
{
InitializeComponent();//设置窗体的各个属性
//获取本地主机IP
string hostip;
System.Net.IPHostEntry localhostip;
System.Net.IPAddress localaddress;
hostip = System.Net.Dns.GetHostName(); //获取本地计算机的主机名
localhostip = System.Net.Dns.GetHostByName(hostip); //获取指定DNS主机的信息
localaddress = localhostip.AddressList[0]; //localaddr中就是本机ip地址
localip.Text = localaddress.ToString();
sendip.Text = localaddress.ToString();
//启动消息接收线程
try
{
localaddressip = IPAddress.Parse(localip.Text);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
Thread receiveMessageThread = new Thread(receiveMessage);
receiveMessageThread.IsBackground = true;
receiveMessageThread.Start();
}
private void receiveMessage()
{
IPAddress ip = IPAddress.Parse(this.localip.Text);//声明一个需要监听的端口
IPEndPoint sendlocalip = new IPEndPoint(ip, port);
myudp = new UdpClient(sendlocalip);
IPEndPoint remoteipandport = new IPEndPoint(IPAddress.Any, 0);
while (true)
{
try
{
//同步接收消息
byte[] GetDate = myudp.Receive(ref remoteipandport);
string msg = Encoding.Unicode.GetString(GetDate);
//将消息显示在列表中
if (msg == "服务器已和你结束聊天")
{
MessageBox.Show("退出");
Application.Exit();//
}
txtmsg.Items.Add(msg);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
break;
}
}
}
//窗体加载启动事件
private void 点对点_Load(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls = false;//防止线程访问出错
}
private void btnsend_Click(object sender, EventArgs e)
{
txtsend.Focus();
byte[] bytes = null;
//如果消息为空则不能发送
if (txtsend.Text == "")
{
MessageBox.Show("消息不能为空");
return;
}
try
{
IPAddress remoteipaddress = IPAddress.Parse(sendip.Text);
}
//发送错误信息显示
catch (Exception ex)
{
MessageBox.Show("ip地址无效");
}
finally
{
}
//启动消息发送线程
Thread sendmessage = new Thread(sendMessage);
sendmessage.IsBackground = true;
string o = (System.DateTime.Now.ToString() + " " + name.Text + ":" + txtsend.Text);
sendmessage.Start(o);
//清空txtsend的内容
txtsend.Clear();
//光标还原
}
//建立一个委托
private delegate void listsendmsgCallBack();
private void sendMessage(object o)
{
listsendmsgCallBack callback = delegate()//使用委托
{
udp = new UdpClient();
string str = (string)o;
byte[] bytes = System.Text.Encoding.Unicode.GetBytes(str);
try
{
sendremoteip = IPAddress.Parse(sendip.Text);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
IPEndPoint remoteipendpoint2 = new IPEndPoint(sendremoteip, port);
try
{
udp.Send(bytes, bytes.Length, remoteipendpoint2);
listsendmsg.Items.Add(str);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
};
listsendmsg.Invoke(callback);
}
private void localip_TextChanged(object sender, EventArgs e)
{
}
private void sendip_TextChanged(object sender, EventArgs e)
{
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
private void name_TextChanged(object sender, EventArgs e)
{
}
private void listsendmsg_SelectedIndexChanged(object sender, EventArgs e)
{
}
private void txtmsg_SelectedIndexChanged(object sender, EventArgs e)
{
}
private void txtsend_TextChanged(object sender, EventArgs e)
{
}
}
}
运行结果
群组聊天
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.Net;
using System.Net.Sockets;
namespace myclient
{
public partial class myudp : Form
{
private UdpClient mylocaludp;
private UdpClient myclient;
private const int port = 33333;
private IPAddress hostip;
private IPAddress remoteipaddress;
public myudp()
{
InitializeComponent();
//获取本地主机IP
string hostip;
System.Net.IPHostEntry localhostip;
System.Net.IPAddress localaddress;
hostip = System.Net.Dns.GetHostName(); //获取本地计算机的主机名
localhostip = System.Net.Dns.GetHostByName(hostip); //获取指定DNS主机名DNS的信息
localaddress = localhostip.AddressList[0]; //localaddr中就是本机ip地址
localip.Text = localaddress.ToString();
sendip.Text = localaddress.ToString();
try
{
localaddress = IPAddress.Parse(localip.Text);
}
catch
{
MessageBox.Show("本地IP设置错误!");
}
//启动消息接收线程
Thread receiveMessageThread = new Thread(receiveMessage);
receiveMessageThread.IsBackground = true;
receiveMessageThread.Start();
}
private void receiveMessage()
{
IPAddress ip = IPAddress.Parse(this.localip.Text);
IPEndPoint sendlocalip = new IPEndPoint(ip, port);
mylocaludp = new UdpClient(sendlocalip);
IPEndPoint remoteipandport = new IPEndPoint(IPAddress.Any, 0);
while (true)
{
try
{
//同步阻塞接收消息
byte[] GetDate = mylocaludp.Receive(ref remoteipandport);
string msg = Encoding.Unicode.GetString(GetDate);
//将消息显示在列表中
if (msg == "服务器已和你结束聊天")
{
MessageBox.Show("结束");
Application.Exit();//停止在所有线程上运行的所有消息循环,并关闭应用程序的所有窗口。
}
txtmsg.Items.Add(msg);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
break;
}
}
}
private void btnsend_Click(object sender, EventArgs e)
{
byte[] bytes = null;
//如果消息为空则不能发送
if (txtsend.Text == "")
{
MessageBox.Show("消息不能为空");
return;
}
try
{
remoteipaddress = IPAddress.Parse(sendip.Text);
}
//发送错误信息显示
catch (Exception ex)
{
MessageBox.Show("ip地址无效");
}
//启动消息发送线程
Thread sendmessage = new Thread(sendMessage);
sendmessage.IsBackground = true;
string o = (System.DateTime.Now.ToString() + " " + name.Text + ":" + txtsend.Text);
sendmessage.Start(o);
//清空txtsend的内容
txtsend.Clear();
//光标还原
txtsend.Focus();
}
private void sendMessage(object o)
{
myclient = new UdpClient();
string str = (string)o;
byte[] bytes = System.Text.Encoding.Unicode.GetBytes(str);
try
{
remoteipaddress = IPAddress.Parse(sendip.Text);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
IPEndPoint remoteipendpoint2 = new IPEndPoint(remoteipaddress, 50000);
try
{
myclient.Send(bytes, bytes.Length, remoteipendpoint2);
listsendmsg.Items.Add(str);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void myudp_Load(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls = false;//防止线程访问出错
}
private void name_TextChanged(object sender, EventArgs e)
{
}
}
}
运行结果
八、课设心得体会
这次课程设计,面对的是一个不熟悉的编程语言,所以这次课设是在边学习边实践的基础上完成的,是在理解网络的基础上对编程的一次学习过程,虽然做的不是很完善,但也学到了很多知识。例如,对c#语句有了一个大体的了解,并且可以简单运用;在创建窗体时,由于对有些控件不了解,所以在应用时,查找了一些相关资料,学会了如何添加和使用。这对自己以后进行网络开发有很大的帮助。本次课程设计是利用C#语言编写的虽说自己以前并没有接触过这种语言,但是经过这两周的学习,我受益匪浅。首先,我弄懂了C#语言的编程方法和原则,并学会了编写C#程序。本次课程设计是实现一个UDP即时通讯程序。经过编写程序和运行,调试程序,我对C#语言有了更深的了解。另外,使我对UDP协议的特点和工作过程有了更深的了解。UDP协议提供无连接的、不可靠的服务。它工作于传输层,是传输层的重要协议之一。最后,UDP协议是利用客户端和服务器端模型来实现传输的。本次课程设计使我明白了知识的重要性,同时也更加懂得实践更不可少。我们要经常把所学的知识运用到实践,这样,才能充分的融会贯通。同时,我也认识到自己的动手实践能力欠缺,所以在以后的学习过程中,要注意培养自己这方面的能力。总之,虽然这次课设程序和界面设计的都不太完美,还有很多需要改进的地方,但是通过这次课设,我收获了很多,能力得到了提高。