UDP局域网QQ聊天程序设计说明书
- 格式:doc
- 大小:113.56 KB
- 文档页数:15
计算机网络与通讯创新试验基于UDP的网络通讯软件侯秦三这个软件主要功能是以UDP为基础实现两台电脑之间收发简单文本消息。
软件全部使用java编写,并以JavaBuilder8为工具进行编写与调试。
布局方式采用NULL方式,主要使用AWT的组件和部分SWING的组件。
使用方法如下:1 首先在输入IP地址的输入栏中输入想与之进行通信的主机的IP地址,即消息接受方的IP地址。
2 在消息编辑框中输入想发送的消息内容。
3 编辑完欲发送的消息后,点击“发送消息”按钮进行发送;4 双方发送的消息和发送方与接受方的IP地址都会在下面的空白区域----“频道”内显示。
6 如果没有输入IP地址便发送编辑完的文本消息,空白区域内会显示出提示信息提示用户应输入接受方的IP地址。
7 当频道内显示的消息太多时,可以按”刷新频道”来清除频道内全部信息!软件运行时候的抓图:本机测试结果的抓图效果程序代码与简要说明1 chatFrame类的代码:package chat;import .*;import java.io.*;import java.awt.*;import java.awt.event.*;import javax.swing.*;/*** <p>Title: </p>* <p>Description: </p>* <p>Copyright: Copyright (c) 2004</p>* <p>Company: </p>* @author not attributable* @version 1.0*/public class chatFrame extends JFrame {JPanel contentPane;Label label1 = new Label();TextField textField1 = new TextField();Label label2 = new Label();TextField textField2 = new TextField();Button button1 = new Button();TextArea textArea1 = new TextArea();DatagramPacket sendpacket,receivepacket; //定义发送和接受数据包DatagramSocket sendsocket,receivesocket;//定义发送和接受DatagramSocket//Construct the framepublic chatFrame() {enableEvents(AWTEvent.WINDOW_EVENT_MASK);try {jbInit();}catch(Exception e) {e.printStackTrace();}}//Component initializationprivate void jbInit() throws Exception { //定义个组件和他们的布局contentPane = (JPanel) this.getContentPane();label2.setAlignment(Label.CENTER);label2.setFont(new java.awt.Font("SansSerif", 0, 15));label2.setForeground(Color.black);label2.setText("消息编辑框");label1.setBounds(new Rectangle(14, 17, 133, 32));contentPane.setLayout(null);this.setSize(new Dimension(500, 400));this.setTitle("用UDP实现聊天");textField1.setBackground(SystemColor.text);textField1.setColumns(0);textField1.setFont(new java.awt.Font("Dialog", 0, 16));textField1.setText("");textField1.setBounds(new Rectangle(129, 72, 200, 61));label1.setAlignment(Label.CENTER);label1.setFont(new java.awt.Font("Dialog", 0, 15));label1.setText("输入对方IP地址");label2.setBounds(new Rectangle(23, 86, 108, 28));try{sendsocket=new DatagramSocket(5000); //初始化receivesocket=new DatagramSocket(5001);}catch(SocketException se){ //可能产生Socketexception类的异常se.printStackTrace();System.exit(0);}button1.setBackground(Color.magenta);button1.setFont(new java.awt.Font("Dialog", 0, 13));button1.setLabel("发送消息");button1.setBounds(new Rectangle(374, 23, 88, 42));button1.addActionListener(new java.awt.event.ActionListener (){public void actionPerformed(ActionEvent e){button1_actionPerformed(e);}});textField2.setBackground(SystemColor.activeCaptionBorder);textField2.setFont(new java.awt.Font("Dialog", 1, 18));textField2.setLocale(java.util.Locale.getDefault());textField2.setText("");textField2.setBounds(new Rectangle(166, 21, 169, 29));textArea1.setFont(new java.awt.Font("Dialog", 0, 13));textArea1.setText("");textArea1.setBounds(new Rectangle(46, 157, 382, 185));contentPane.setBackground(new Color(113, 111, 159));jButton1.setBackground(Color.pink);jButton1.setBounds(new Rectangle(374, 86, 87, 42));jButton1.setFont(new java.awt.Font("Dialog", 0, 13));jButton1.setText("刷新频道");jButton1.addActionListener(new java.awt.event.ActionListener() {public void actionPerformed(ActionEvent e) {jButton1_actionPerformed(e);}});contentPane.add(label1, null);contentPane.add(textField2, null);contentPane.add(textField1, null);contentPane.add(label2, null);contentPane.add(textArea1, null);contentPane.add(jButton1, null);contentPane.add(button1, null);}//Overridden so we can exit when window is closedprotected void processWindowEvent(WindowEvent e) {super.processWindowEvent(e);if (e.getID() == WindowEvent.WINDOW_CLOSING) {System.exit(0);}}public void waitforpackets(){ //这个方法完成接受数据包的功能while(true){try{byte[]array=new byte[100];receivepacket=new DatagramPacket(array,array.length);//创建接受数据包的缓冲receivesocket.receive(receivepacket);//接受数据包textArea1.append("\nfrom "+receivepacket.getAddress() +" : ");byte data[]=receivepacket.getData();String received=new String(data,0);//将字节数组转化为字符串textArea1.append(received);}catch(IOException se){//可能产生的IOException类异常textArea1.append(se.toString() +"/n");se.printStackTrace();}}}void button1_actionPerformed(ActionEvent e){//这个方法完成发送数据包String str = textField2.getText();if(pareTo("")!=0){try{textArea1.append("\nto "+textField2.getText() +" : "+textField1.getText());String s=textField1.getText();byte data[]=new byte[100];s.getBytes(0,s.length(),data,0);sendpacket=new DatagramPacket(data,s.length(),InetAddress.getByName(textField2.getText()),5001);//创建发送的数据包sendsocket.send(sendpacket);//发送数据包}catch(IOException exc){textArea1.append(exc.toString() +"\n");exc.printStackTrace();}}elsetextArea1.setText("please input your friend's IP first!");}JButton jButton1 = new JButton();void jButton1_actionPerformed(ActionEvent e) {textArea1.setText("");}}2.chatapp类的代码:package chat;import .*;import java.io.*;import javax.swing.UIManager;import java.awt.*;/*** <p>Title: </p>* <p>Description: </p>* <p>Copyright: Copyright (c) 2004</p>* <p>Company: </p>* @author not attributable* @version 1.0*/public class chatApp {boolean packFrame = false;//Construct the applicationpublic chatApp() {chatFrame frame = new chatFrame();//Validate frames that have preset sizes//Pack frames that have useful preferred size info, e.g. from their layoutif (packFrame) {frame.pack();}else {frame.validate();}//Center the windowDimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();Dimension frameSize = frame.getSize();if (frameSize.height > screenSize.height) {frameSize.height = screenSize.height;}if (frameSize.width > screenSize.width) {frameSize.width = screenSize.width;}frame.setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2);frame.setVisible(true);frame.waitforpackets();}//Main methodpublic static void main(String[] args) {try {UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());}catch(Exception e) {e.printStackTrace();}new chatApp();}}。
c udp聊天程序课程设计一、课程目标知识目标:1. 学生能理解UDP协议的工作原理和特点,掌握UDP编程的基本方法;2. 学生能运用C语言实现简单的UDP聊天程序,了解网络编程中的数据传输和接收过程;3. 学生了解网络通信中IP地址、端口号等基本概念,并掌握其在编程中的应用。
技能目标:1. 学生能够独立编写和调试C语言UDP聊天程序,具备基本的网络编程能力;2. 学生能够分析并解决网络编程过程中遇到的问题,具备问题解决能力;3. 学生能够通过实际操作,提高编程实践能力和团队协作能力。
情感态度价值观目标:1. 学生通过学习UDP聊天程序的制作,培养对网络编程的兴趣和热情;2. 学生在编程实践中,学会克服困难,培养坚持不懈、勇于探索的精神;3. 学生通过团队协作,培养良好的沟通能力和团队合作精神。
分析课程性质、学生特点和教学要求,本课程将目标分解为以下具体学习成果:1. 学生能够掌握UDP协议的基本原理,并能够运用C语言实现简单的网络通信;2. 学生能够独立编写和调试UDP聊天程序,具备基本的网络编程能力;3. 学生能够在课程实践中,培养良好的编程习惯和团队合作精神。
二、教学内容1. UDP协议原理:介绍UDP协议的特点、工作原理及其在网络通信中的应用,关联课本第三章第二节。
2. C语言网络编程基础:回顾C语言的基本语法,重点讲解socket编程、数据类型转换等在网络编程中的应用,关联课本第四章。
3. UDP聊天程序设计:详细讲解UDP聊天程序的设计思路、步骤及关键代码实现,包括以下内容:- 创建UDP套接字;- 绑定IP地址和端口号;- 发送和接收数据;- 关闭套接字。
关联课本第五章第三节。
4. 编程实践:安排学生进行UDP聊天程序的编写和调试,分为以下阶段:- 阶段一:实现UDP套接字的创建、绑定和关闭;- 阶段二:实现数据的发送和接收;- 阶段三:优化程序,处理异常情况,提高程序的稳定性和用户体验。
研究生课程论文课程名称面向对象程序设计VC++授课学期2012 学年至2013 学年第 1 学期学院电子工程学院专业电子和通信工程学号2012011597姓名潘睿哲任课教师黄守麟李廷会交稿日期2013.4.10成绩阅读教师签名日期广西师范大学研究生学院制基于UDP协议的聊天工具的设计第一章需求分析1.1 功能需求①用户之间能够通过输入IP地址建立连接②用户能够输入所需发送的信息,并能够在界面上发看到输入的信息③用户之间可以相互通信1.2 使用平台需求安装有VS2008的操作系统,能够正常运行EXE文件。
1.3 界面的设计需求本程序利用UDP协议来进行通信,因此可以简单地将发送端和接收端集成在同一个对话框界面上,并可以通过利用多线程技术以保证接受信息功能的顺畅。
1.4 简单流程图图1-1第二章 概要设计2.1 程序总体结构图发送端 接收端图2-12.2 发送端流程 图2-22.3 接收端流程图2-3第三章 详细设计3.1 界面设计建立连接 聊天(发送、接受信息) 结 束创建套接字 创建接收线程 实现线程函数 接受消息消息转换输入消息 显示消息 发送消息 创建套接字Bind 绑定 创建套接字 输入消息 显示消息 发送消息 创建接收线程实现线程函数创建套接字 Bind 绑定图3-1说明:界面由一个对话框,两个编辑框,一个按钮和一个IP地址编辑框组成。
其中接收数据栏中的编辑框可以显示发送的信息和接收到的信息,发送数据栏中编辑框则可以编辑发送信息,按回车键后即可发送信息。
IP地址栏中可以输入需要连接的主机的IP地址。
为了美观和方便,在添加按钮后,选中按钮控件的DEFAULT和VISIALBE属性,将其设定为不可见,并通过回车能够实现按钮功能。
3.2 多线程由于该聊天工具是将利用UDP协议实现聊天功能,并将发送端和接收端(某种意义上也可以算是服务器和客户端)集成在一起,为了将发送功能和接受功能同时实现,需要用到多线程技术。
基于UDP的P2P模式的聊天程序一、课题内容和要求使用UDP协议编写聊天软件,使得客户端之间可以自由地进行键盘聊天。
【程序的具体要求】1)以图形界面运行, 提供聊天内容输入界面和收到的文字聊天内容。
2)允许客户选择不同的其他客户方(peer)进行聊天,假定已知对方的IP地址。
二、需求分析本次试验需要使用UDP协议的P2P模式,所以在试验之前应该对其进行一定了解。
UDP 是User Datagram Protocol的简称,中文名是用户数据包协议,是 OSI 参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。
UDP是ISO 参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。
UDP 协议基本上是IP协议与上层协议的接口。
UDP协议适用端口分辨运行在同一台设备上的多个应用程序。
UDP协议的全称是用户数据报协议,在网络中它与TCP协议一样用于处理UDP 数据包。
在OSI模型中,在第四层——传输层,处于IP协议的上一层。
UDP有不提供数据报分组、组装和不能对数据包的排序的缺点,也就是说,当报文发送之后,是无法得知其是否安全完整到达的。
UDP用来支持那些需要在计算机之间传输数据的网络应用。
包括网络视频会议系统在内的众多的客户/服务器模式的网络应用都需要使用UDP协议。
UDP协议从问世至今已经被使用了很多年,虽然其最初的光彩已经被一些类似协议所掩盖,但是即使是在今天,UDP仍然不失为一项非常实用和可行的网络传输层协议。
与所熟知的TCP(传输控制协议)协议一样,UDP协议直接位于IP(网际协议)协议的顶层。
根据OSI(开放系统互连)参考模型,UDP和TCP都属于传输层协议。
UDP协议的主要作用是将网络数据流量压缩成数据报的形式。
一个典型的数据报就是一个二进制数据的传输单位。
每一个数据报的前8个字节用来包含报头信息,剩余字节则用来包含具体的传输数据。
P2P是英文Peer-to-Peer(对等)的简称,又被称为“点对点”。
TCP/UDP程序开发使用C#制作简易qqTCP、UDP程序开发一.实验课时8学时二.实验目的开发TCP/UDP协议应用程序,掌握网络应用程序的工作原理。
通过本实验,深入理解TCP和UDP协议的异同点,了解网络协议的工作过程,学会网络通信编程的基本方法,能够编制网络应用程序。
三.实验内容(1)了解和掌握“基于UDP——面向无连接的应用程序”和“基于TCP——面向连接的应用程序”的运行机制和编程方法。
(2)选择以下一个内容,编写一个网络通信应用程序①聊天程序;②邮件收发程序;③HTTP服务器程序。
四.实验要求(1)使用任意编程语言(如Java,C,VB,Delphi等)编写基于TCP或UDP协议的网络应用程序。
(2)总结实验过程,内容包括:方案、程序、调试、结果、分析、结论。
五.实验设备(1)硬件要求:计算机、Internet网。
(2)软件要求:Windows操作系统、相关软件开发工具(如Microsoft Visual Studio,JDK等)。
六.预习要求(1)复习TCP/UDP协议原理。
(2)复习应用进程跨越网络通信的基本编程方法。
(3)复习聊天、邮件、HTTP服务的相关原理。
(4)熟悉相关编程语言及编程工具环境。
七.注意事项(1)遵守实验纪律,爱护实验设备。
(2)提交详细实验报告一份。
实验过程和结果不能简单地复制相关命令或内容,要有理解和分析。
八.程序代码1.服务器端using System;using System.Collections.Generic;using ponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using ;using .Sockets;using System.Threading;using System.IO;namespace WindowsFormsApplication1{public partial class Form1 : Form{public Form1(){InitializeComponent();this.Init();tab2.Visible = true;tab3.Visible = false;tab1.Visible = false;}private void btnLog_Click(object sender, EventArgs e){if (txtIP.Text == "" || txtPort.Text == ""){MessageBox.Show("请输入IP地址或端口号!", "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1);return;}else{try{IPAddress ipadd = IPAddress.Parse(this.txtIP.Text);int port = Convert.ToInt32(this.txtPort.Text);tab3.Visible = true;tab1.Visible = true;this.Init2();this.btnImgFile.Enabled = false;this.Text = "服务器"+ DateTime.Now.ToString() + " "+ DateTime.Now.DayOfWeek.ToString();richTextBox1.AppendText("System:服务器已进入聊天室!?<-"+ DateTime.Now.ToLongTimeString() + "->.....\r\n");string SerIp = txtIP.Text.ToString();string SerPort = txtPort.Text.ToString();labip.Text = " IP地址:" + " " + SerIp + " ";labport.Text = " 端口号:" + " " + SerPort;}catch (Exception){MessageBox.Show("您输入的IP地址或端口号不正确,\n请重新输入!", "错误 ", MessageBoxButtons.OK, MessageBoxIcon.Error);}}}//重置服务器信息private void btnResent_Click_1(object sender, EventArgs e){txtIP.Clear();txtPort.Clear();}private void Init(){richTextBox1.Visible = false;txt1_sendinfo.Visible = false;}private void Init2(){richTextBox1.Visible = true;txt1_sendinfo.Visible = true;}private OpenFileDialog openfiledialog = new OpenFileDialog();private SaveFileDialog savefiledialog = new SaveFileDialog();private byte[] img;//传输图片用字节数组private int imgflag = 0;private FileStream fstream;public delegate void UpdateRichTextBox(string msg);//异步委托代理public delegate void UpdateImg(Stream s);private Socket socket; //服务器端套接字private Socket clientSocket; //客户端连接套接字private Thread thread;//启动服务器,开始监听private void btn_start_Click(object sender, EventArgs e){try{IPAddress ip = IPAddress.Parse(this.txtIP.Text);IPEndPoint server = new IPEndPoint(ip, Int32.Parse(this.txtPort.Text));//创建服务器套接字socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);socket.Bind(server);//绑定端口号socket.Listen(10);thread = new Thread(new ThreadStart(AcceptMessage));thread.Start();//开始监听this.Text = " 服务器Taking....";richTextBox1.Clear();richTextBox1.AppendText("System:服务器已启动!<-"+ DateTime.Now.ToLongTimeString() + "->.....\r\n");btnImgFile.Enabled = true;btn_start.Enabled = false;btn_stop.Enabled = true;}catch (Exception ex){MessageBox.Show("服务器: " + ex.Message);this.btn_start.Enabled = true;}}//接收客户端信息public void AcceptMessage() //异步接收信息后台线程方法{this.clientSocket = socket.Accept();this.richTextBox1.Clear();richTextBox1.AppendText("System:服务器连接成功!?<-"+ DateTime.Now.ToLongTimeString() + "->.....\r\n");while (true){try{if(this.clientSocket == null|| this.clientSocket.Connected == false)break;NetworkStream netStream = new NetworkStream(this.clientSocket);//通clientSocket对象获取NetworkStream对象//得到一条消息的长度byte[] dataSize = new byte[4];netStream.Read(dataSize, 0, 4);int size = System.BitConverter.ToInt32(dataSize, 0);//循环接收直到一条完整的消息全部读入到字节数组中byte[] message = new byte[size];int dataleft = size;int start = 0;if (size > 0){while (dataleft > 0){int recv = netStream.Read(message, start, dataleft);start += recv;dataleft -= recv;}if (message[0] == 101)//101代表传输图片{MemoryStream ms = new MemoryStream(message, 1, message.Length - 1);richTextBox1.BeginInvoke(new UpdateImg(ViewImg), new object[] { ms });}else//默认进行普通传输{string Msg = System.Text.Encoding.Unicode.GetString(message, 1, message.Length - 1);this.richTextBox1.BeginInvoke(newUpdateRichTextBox(UpdateMessage), new object[] { Msg });}}Thread.Sleep(100);}catch (.Sockets.SocketException se){MessageBox.Show("服务器:" + se.Message);}}}//点击“发送”按钮private void btn_send_Click(object sender, EventArgs e){if (txt1_sendinfo.Text == ""){MessageBox.Show("请先输入内容!");txt1_sendinfo.Clear();txt1_sendinfo.Focus();return;}if (imgflag == 1){//发送图片?byte[] imgSize = new byte[4];//将32位整数值转换为字节数组imgSize = System.BitConverter.GetBytes(img.Length + 1);//其中加1是因为后面了一个101做分隔符try{NetworkStream netStream = new NetworkStream(clientSocket);netStream.Write(imgSize, 0, 4);netStream.WriteByte(101);//分隔符netStream.Write(img, 0, img.Length);netStream.Flush();this.richTextBox1.SelectionColor = Color.SteelBlue;this.richTextBox1.AppendText("服务器<-"+ DateTime.Now.ToLongTimeString() + "->:\r\n");this.richTextBox1.SelectionStart = this.richTextBox1.Text.Length;Clipboard.SetDataObject(Image.FromStream(fstream));richTextBox1.Paste();this.richTextBox1.SelectionColor = Color.SteelBlue;this.richTextBox1.AppendText("\n");fstream.Flush();fstream.Close();//此流必须在这里才可以消除txt1_sendinfo.Paste();this.richTextBox1.SelectionStart = this.richTextBox1.Text.Length;this.richTextBox1.Focus();this.txt1_sendinfo.Text = "";this.txt1_sendinfo.Focus();imgflag = 0;//复原return;//不执行后面的传输文本信息}catch (System.Exception ex){MessageBox.Show("服务器:" + ex.Message);}}//发送文本信息this.richTextBox1.SelectionColor = Color.SteelBlue;string str = "服务器<-"+ DateTime.Now.ToLongTimeString() + "->:\r\n"+ txt1_sendinfo.Text;int i = str.Length;if (i == 0){return;}else{//因为str为Unicode编码,每个字符占2个字节,所以实际字节数应为字符个数*2 i *= 2;}byte[] dataSize = new byte[4];//将32位整数值转换为字节数组dataSize = System.BitConverter.GetBytes(i + 1);//其中加1是因为后面写了一个1做分隔符byte[] sendbytes = System.Text.Encoding.Unicode.GetBytes(str);try{NetworkStream netStream = new NetworkStream(clientSocket);netStream.Write(dataSize, 0, 4);netStream.WriteByte(1);//分隔符netStream.Write(sendbytes, 0, sendbytes.Length);netStream.Flush();richTextBox1.SelectionColor = Color.SteelBlue;this.richTextBox1.AppendText(str + "\n");this.richTextBox1.SelectionStart = this.richTextBox1.Text.Length;this.richTextBox1.Focus();this.txt1_sendinfo.Rtf = "";this.txt1_sendinfo.Focus();}catch (System.Exception ex){MessageBox.Show("服务器:" + ex.Message);}}//断开连接private void btn_stop_Click(object sender, EventArgs e){socket.Close();thread.Abort();thread.Join(10);this.btn_start.Enabled = true;btn_stop.Enabled = false;this.btnImgFile.Enabled = false;this.Text = " 服务器"+ DateTime.Now.ToString() + " "+ DateTime.Now.DayOfWeek.ToString();this.richTextBox1.AppendText("System:服务器断开连接!<-"+ DateTime.Now.ToLongTimeString() + "->..... \r\n");}//接收文本private void UpdateMessage(string strmsg) //将异步接收到的信息显示在文本框里{this.richTextBox1.SelectionColor = Color.LightCoral;this.richTextBox1.AppendText(strmsg + "\n");this.richTextBox1.SelectionStart = this.richTextBox1.Text.Length;this.richTextBox1.Focus();this.txt1_sendinfo.Focus();}//接收图片信息private void ViewImg(Stream s) //将异步接收到的信息显示在文本框里{richTextBox1.SelectionStart = richTextBox1.Text.Length;richTextBox1.SelectionColor = Color.LightCoral;richTextBox1.AppendText("服务器接收图片<-"+ DateTime.Now.ToLongTimeString() + "->:\r\n");Clipboard.SetDataObject(Image.FromStream(s));//利用剪切板richTextBox1.Paste();richTextBox1.SelectionColor = Color.LightCoral;richTextBox1.AppendText("\n");richTextBox1.SelectionStart = richTextBox1.Text.Length;richTextBox1.Focus();txt1_sendinfo.Focus();}//上传图片文件中的图片private void btnImgFile_Click(object sender, EventArgs e){openfiledialog.Filter = "所有文件t(*.*)|*.*|位图文(*.bmp)|*.bmp|文件t (.jpg)|*.jpg|文件t(.gif)|*.gif";if (openfiledialog.ShowDialog() == DialogResult.OK){String strpath = openfiledialog.FileName;fstream = new FileStream(strpath, FileMode.Open);BinaryReader breader = new BinaryReader(fstream);img = breader.ReadBytes((int)fstream.Length);Clipboard.SetDataObject(Image.FromStream(fstream));txt1_sendinfo.Paste();imgflag = 1;}}//退出聊天室private void btn_Exit_Click(object sender, EventArgs e){if (btn_stop.Enabled != true){this.Close();Application.Exit();}else{MessageBox.Show("请先断开连接!");return;}}//取消发送private void btnRest_Click(object sender, EventArgs e){txt1_sendinfo.Clear();}//清屏private void btnClear_Click(object sender, EventArgs e){this.richTextBox1.Clear();}}2.客户端using System;using System.Collections.Generic;using ponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using ;using .Sockets;using System.Threading;using System.IO;namespace WindowsFormsApplication1{public partial class Form1 : Form{public Form1(){InitializeComponent();this.Init();tab2.Visible = true;tab3.Visible = false;tab1.Visible = false;}private void Init(){this.richTextBox1.Visible = false;this.txt2_send.Visible = false;}private void Init2()this.richTextBox1.Visible = true;this.txt2_send.Visible = true;}//登录聊天室private void btnLog_Click(object sender, EventArgs e){if (txtIP.Text == "" || txtPort.Text == ""){MessageBox.Show("服务器信息不能为空!", "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1);return;}if (txtName.Text == ""){MessageBox.Show("请输入您的呢称!", "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1);return;}else{try{IPAddress ipadd = IPAddress.Parse(this.txtIP.Text);int port = Convert.ToInt32(this.txtPort.Text);userName = txtName.Text.ToString();tab1.Visible = true;this.Init2();tab3.Visible = true;this.btnImgFile.Enabled = false;this.Text = " " + userName + " " + DateTime.Now.ToString() + " " + DateTime.Now.DayOfWeek.ToString();richTextBox1.AppendText("System:"+ userName + " 已进入聊天室!<-"+ DateTime.Now.ToLongTimeString() + "->.....\r\n");string SerIp = txtIP.Text.ToString();string SerPort = txtPort.Text.ToString();lbSerIp.Text = " IP地址 :" + " " + SerIp + " ";lbSerPort.Text = " 端口号?:" + " " + SerPort;}catch (Exception){MessageBox.Show("您输入的服务器信息不合法,\n请重新输入!", "错误",MessageBoxButtons.OK, MessageBoxIcon.Error);}}}//重置服务器信息和昵称private void btnResent_Click(object sender, EventArgs e){txtIP.Clear();txtPort.Clear();txtName.Clear();}private OpenFileDialog openfiledialog = new OpenFileDialog();private SaveFileDialog savefiledialog = new SaveFileDialog();private byte[] img;//保存传图片时的字节数组private int imgflag = 0;private FileStream fstream;public delegate void UpdateMessage(string msg);public delegate void UpdateImg(Stream s);private Socket socket;private Thread thread;public string userName;//与服务器连接private void btn_req_Click(object sender, EventArgs e){try{IPAddress ip = IPAddress.Parse(this.txtIP.Text);IPEndPoint server = new IPEndPoint(ip, Int32.Parse(this.txtPort.Text));//创建客户端套接字socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);socket.Connect(server);//连接thread = new Thread(new ThreadStart(AcceptMessage));thread.Start();this.Text = " " + userName + " Taking....";richTextBox1.Clear();richTextBox1.AppendText("System:" + userName + " 连接到服务器!<-" + DateTime.Now.ToLongTimeString() + "->.....\r\n");btn_req.Enabled = false;btn_close.Enabled = true;btnImgFile.Enabled = true;}catch{richTextBox1.Clear();richTextBox1.AppendText("System:" + userName + " 未连接上服务器!<-" + DateTime.Now.ToLongTimeString() + "->.....\r\n");return;}}//接收后台接收消息public void AcceptMessage() //异步接收信息后台线程方法{while (true){try{if (this.socket == null || this.socket.Connected == false){richTextBox1.Clear();richTextBox1.AppendText("System:" + userName + "未连接上服务器!<-" + DateTime.Now.ToLongTimeString() + "->.....\r\n");break;}NetworkStream netStream = new NetworkStream(this.socket);//必须放在if后,this.socket可能没实例化//得到一条消息的长度byte[] dataSize = new byte[4];//前4字节代表后面字节总数,发送时骸已经处理过了try{netStream.Read(dataSize, 0, 4);}catch (Exception){}int size = System.BitConverter.ToInt32(dataSize, 0);//循环接收直到一条完整的消息全部读入到字节数组中byte[] message = new byte[size];int dataleft = size;int start = 0;while (dataleft > 0){int recv = netStream.Read(message, start, dataleft);start += recv;dataleft -= recv;}if (message[0] == 101)//101代表传输图片{MemoryStream ms = new MemoryStream(message, 1, message.Length - 1); richTextBox1.BeginInvoke(new UpdateImg(ViewImg), new object[] { ms });}else//默认进行普通传输{string Msg = System.Text.Encoding.Unicode.GetString(message, 1, message.Length - 1);richTextBox1.BeginInvoke(new UpdateMessage(ViewMessage), new object[] { Msg });}Thread.Sleep(100);}catch (.Sockets.SocketException ex){MessageBox.Show(userName + ":" + ex.Message);}}}//传输文件private void ViewMessage(string msg){richTextBox1.SelectionColor = Color.SteelBlue;richTextBox1.AppendText(msg + "\n");richTextBox1.SelectionStart = richTextBox1.Text.Length;//定位到最后,保持最新消息可见richTextBox1.Focus();txt2_send.Focus();}//接收图片信息private void ViewImg(Stream s){richTextBox1.SelectionStart = richTextBox1.Text.Length;richTextBox1.SelectionColor = Color.SteelBlue;richTextBox1.AppendText(userName + "接收图片<-"+ DateTime.Now.ToLongTimeString() + "->:\r\n");Clipboard.SetDataObject(Image.FromStream(s));//利用剪切板richTextBox1.Paste();richTextBox1.SelectionColor = Color.SteelBlue;richTextBox1.AppendText("\n");richTextBox1.SelectionStart = richTextBox1.Text.Length;richTextBox1.Focus();txt2_send.Focus();}//点击发送按钮private void btn_send_Click(object sender, EventArgs e){if (txt2_send.Text == ""){MessageBox.Show("请先输入内容!");txt2_send.Clear();txt2_send.Focus();return;}if (imgflag == 1)//imgflag的值在方法tnImgFile_Click中可能改变{//当传输图片时byte[] imgSize = new byte[4];//将32位整数值转换为字节数组imgSize = System.BitConverter.GetBytes(img.Length + 1);//后面一个标识数:101try{NetworkStream netStream = new NetworkStream(this.socket);netStream.Write(imgSize, 0, 4);netStream.WriteByte(101);//标识数netStream.Write(img, 0, img.Length);netStream.Flush();this.richTextBox1.SelectionColor = Color.LightCoral;this.richTextBox1.AppendText(userName + "<-"+ DateTime.Now.ToLongTimeString() + "->:\r\n");this.richTextBox1.SelectionStart = this.richTextBox1.Text.Length;Clipboard.SetDataObject(Image.FromStream(fstream));richTextBox1.Paste();richTextBox1.SelectionColor = Color.LightCoral;this.richTextBox1.AppendText("\n");fstream.Flush();fstream.Close();//此流必须在这里才可以消除txt2_send.Paste();this.richTextBox1.SelectionStart = this.richTextBox1.Text.Length;this.richTextBox1.Focus();this.txt2_send.Text = "";this.txt2_send.Focus();imgflag = 0;//复原return;//不执行后面的传输文本信息}catch (System.Exception ex){MessageBox.Show("服务器:" + ex.Message);}}//发送文本信息时this.richTextBox1.SelectionColor = Color.LightCoral;string str = userName + "<-" + DateTime.Now.ToLongTimeString() + "->:阰\r\n" + txt2_send.Text;int i = str.Length;if (i == 0){return;}else{//因为str为Unicode编码,每个字符占2个字节,所以实际字节数应为字符个数*2 i *= 2;}byte[] dataSize = new byte[4];//将32位整数值转换为字节数组dataSize = System.BitConverter.GetBytes(i + 1);//后面一个标识数:1 byte[] sendbytes = System.Text.Encoding.Unicode.GetBytes(str);try{NetworkStream netStream = new NetworkStream(this.socket);netStream.Write(dataSize, 0, 4);netStream.WriteByte(1);//标识数netStream.Write(sendbytes, 0, sendbytes.Length);netStream.Flush();richTextBox1.SelectionColor = Color.LightCoral;this.richTextBox1.AppendText(str + "\n");richTextBox1.SelectionStart = richTextBox1.Text.Length;richTextBox1.Focus();this.txt2_send.Rtf = "";txt2_send.Focus();}catch (System.Exception ex){MessageBox.Show(userName + ":" + ex.Message);}}//发送图片按钮private void btnImgFile_Click(object sender, EventArgs e){openfiledialog.Filter = "所有文件t(*.*)|*.*|位图文件t(*.bmp)|*.bmp|文件t (.jpg)|*.jpg|文件t(.gif)|*.gif";if (openfiledialog.ShowDialog() == DialogResult.OK){String strpath = openfiledialog.FileName;fstream = new FileStream(strpath, FileMode.Open);//此行和下一行是关键,得到文件字节数组BinaryReader breader = new BinaryReader(fstream);img = breader.ReadBytes((int)fstream.Length);//得到文件数组Clipboard.SetDataObject(Image.FromStream(fstream));txt2_send.Paste();imgflag = 1;}}//断开和服务器端连接óprivate void btn_close_Click(object sender, EventArgs e){socket.Close();thread.Abort();thread.Join(10);this.btn_req.Enabled = true;btn_close.Enabled = false;btnImgFile.Enabled = false;this.Text = " "+ userName + " "+ DateTime.Now.ToString() + " "+ DateTime.Now.DayOfWeek.ToString();this.richTextBox1.AppendText("System:" + userName + " 断开与服务器的连接!<-" + DateTime.Now.ToLongTimeString() + "->..... \r\n");}//退出聊天室private void btn_Exit_Click(object sender, EventArgs e){if (btn_close.Enabled != true){this.Close();Application.Exit();}else{MessageBox.Show("请先断开连接!");return;}}//取消发送private void btnRest_Click(object sender, EventArgs e) {txt2_send.Clear();}//清屏private void btnClear_Click(object sender, EventArgs e) {this.richTextBox1.Clear();}}}九.截图十.实验心得。
My聊天程序设计正文:1、引言本文档旨在提供关于My聊天程序设计的详细说明和指导。
My 是一款基于网络的聊天程序,旨在提供轻松、安全和实时的聊天体验。
2、需求分析2.1 功能需求2.1.1 用户注册2.1.2 用户登录2.1.3 添加好友2.1.4 聊天功能2.1.5 发送图片和文件2.1.6 创建群组2.1.7 加入群组2.1.8 群组聊天功能2.2 非功能需求2.2.1 用户界面友好2.2.2 数据安全性2.2.3 实时消息传输3、系统设计3.1 架构设计3.1.1 客户端-服务器模型3.1.2 MVC设计模式3.1.3 数据库设计3.2 用户注册设计3.2.1 用户名和密码校验3.2.2 用户信息存储3.3 用户登录设计3.3.1 账号密码验证3.3.2 登录状态管理3.4 好友管理设计3.4.1 查找好友3.4.2 添加好友3.4.3 删除好友3.5 聊天功能设计3.5.1 单聊功能3.5.2 消息发送和接收3.5.3 消息存储和读取3.6 图片和文件发送设计3.6.1 图片和文件的传输3.6.2 图片和文件的存储3.7 群组聊天设计3.7.1 创建群组3.7.2 邀请成员加入群组3.7.3 群组聊天功能4、系统实现4.1 开发环境4.2 开发技术4.3 数据库选择和配置4.4 代码实现4.5 系统测试5、部署与维护5.1 系统部署5.2 系统维护6、附件本文档所涉及的附件包括:系统架构图、用户界面设计图、数据库设计图、代码实现文档等。
7、法律名词及注释以下是本文档中可能涉及的法律名词及其注释:1. 用户隐私保护:指在用户使用聊天程序过程中,程序应保护用户的个人信息和隐私不被泄露。
2. 数据安全性:指在数据传输和存储过程中,要采取相应的安全措施,确保数据不会被非法获取和篡改。
3. 著作权:指相关程序的著作权归属以及用户在程序中发布内容的可分性和权益。
4. 知识产权:指程序中的程序源代码、界面设计、图像、音频、视频等知识产权的归属和保护。
基于UDP的聊天程序UDP是一种无连接的传输协议,而TCP是一种面向连接的传输协议。
UDP比TCP更适合实时应用,因为它不需要建立稳定的连接和保持状态。
以下是一个基于UDP的聊天程序的简单实现:1. 服务器端```import socket# 创建socket对象s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)# 绑定端口s.bind(('127.0.0.1', 9999))# 等待客户端连接print('Server started...')while True:# 接收消息data, addr = s.recvfrom(1024)print('Received from %s:%s.' % addr)print(data.decode('utf-8'))# 发送消息reply = input('Input message to send: ')s.sendto(reply.encode('utf-8'), addr)```2. 客户端```import socket# 创建socket对象s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)# 输入服务器地址和端口号server_addr = input('Input server address: ')server_port = int(input('Input server port: '))# 发送消息while True:message = input('Input message to send: ')s.sendto(message.encode('utf-8'), (server_addr, server_port))# 接收消息data, addr = s.recvfrom(1024)print('Received from %s:%s.' % addr)print(data.decode('utf-8'))```运行程序后,客户端可以通过命令行输入消息并发送到服务器,服务器接收到消息后发送回复。
制作自己的QQ聊天工具(1)我们知道网络层的传输协议,主要是TCP和UDP两大协议。
UDP主要信息载体是传送数据包,面向无连接;TCP以三次握手建立数据传输通道,然后数据以字节流形式进行网络传输。
基于这俩哥们的不同特点,我们对他们有着不同的用处。
而网络即时聊天工具,需要传输速度快,对可靠性方面要求并不太高,使用UDP协议完全可以实现。
下面就是一个简单的UDP多线程聊天窗口,可以实现局域网内,多人即时聊天:import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.io.IOException;import .DatagramPacket;import .DatagramSocket;import .InetAddress;import .SocketException;import .UnknownHostException;import java.util.TimerTask;import .*;import javax.swing.*;public class MyTalk{static JTextArea myjt1=new JTextArea();static JTextArea myjt2=new JTextArea();static JButton jb1=new JButton("发送");static DatagramSocket myds2=null;static DatagramSocket myds;public static void main(String[] args) throws Exception{myds=new DatagramSocket(10004);myds2=new DatagramSocket();getTKJF();MyRece mr=new MyRece(myds);Thread mytd2=new Thread(mr);mytd2.start();}// 定义窗体界面public static void getTKJF() throws Exception{JFrame myjf1=null;myjt1.setBounds(10, 20, 200, 150);myjt2.setBounds(10, 213, 200,40);jb1.setBounds(220,220,60,25);myjf1=new JFrame("测试UDP");myjf1.setBounds(200, 200, 300, 300);myjf1.add(myjt1);myjf1.add(myjt2);myjf1.add(jb1);MyTalk.jb1.addActionListener(new HandleTKJB(myds2));myjf1.setLayout(null);myjf1.setVisible(true);}}//创建一个接受消息的线程class MyRece implements Runnable{DatagramSocket myds;public MyRece(DatagramSocket myds){this.myds=myds;}public void run() {try{while(true){byte[] myby1=new byte[1024];DatagramPacket mydp=new DatagramPacket(myby1,myby1.length); myds.receive(mydp);byte[] myby2=mydp.getData();String ip=mydp.getAddress().getHostAddress();String str=new String(myby2,0,mydp.getLength());// getJF();MyTalk.myjt1.append(ip+":"+str+"\n");}}catch(Exception e){JOptionPane.showMessageDialog(null, "信息接收失败!");}}}//消息发送线程class MySend implements Runnable{DatagramSocket myds;public MySend(DatagramSocket myds){this.myds=myds;}public void run(){try{String str1=MyTalk.myjt2.getText();if(!str1.equals("")){byte[] myby1=str1.getBytes();DatagramPacket mydp=newDatagramPacket(myby1,myby1.length,InetAddress.getByName("192.168.45.255"),10004 );myds.send(mydp);MyTalk.myjt2.setText("");}else{JOptionPane.showMessageDialog(null, "所发信息不能为空!");}//myds.close();}catch(Exception e){e.printStackTrace();JOptionPane.showMessageDialog(null, "信息发送失败!");}}}//添加按钮事件,触发消息发送线程class HandleTKJB implements ActionListener{DatagramSocket myds;public HandleTKJB(DatagramSocket myds){this.myds=myds;}public void actionPerformed(ActionEvent e){// try {// myds2=new DatagramSocket();// } catch (Exception e1) {// TODO Auto-generated catch block// e1.printStackTrace();// }// MySend ms=new MySend(myds2);// Thread mytd=new Thread(ms);// mytd.start();if(e.getSource()==MyTalk.jb1){MySend ms=new MySend(myds);Thread mytd=new Thread(ms);mytd.start();}}}为了大家容易看懂,我删除了那些复杂难懂的部分,只保留了一些必要的代码,自己如果真心想做,可以再加添一些界面美化,以及附加功能,比如说文件上传,图片上传,发送表情等等,万变不离其中,道理都差不多。
My聊天程序设计My聊天程序设计1. 引言随着互联网的快速发展,人们越来越需要一种方便、高效的聊天工具来进行即时通讯。
而作为目前最流行的聊天软件之一,具备了强大的功能和用户友好的界面,成为很多人的首选。
设计一个类似于的聊天程序是很有意义的。
2. 功能设计2.1 用户注册和登录在使用聊天程序之前,用户需要先进行注册,并创建一个账号和密码。
注册成功后,用户可以使用账号和密码登录聊天程序。
2.2 好友管理聊天程序中,用户可以添加好友,并建立好友列表。
好友列表中显示了每个好友的昵称和状态。
用户可以进行好友的添加、删除和查找等操作。
2.3 即时通讯用户可以使用聊天程序发送和接收文本消息、语音消息、图片等。
程序需要提供一个聊天窗口,用户可以在窗口中选择好友进行聊天,并发送各种类型的消息。
2.4 群组功能除了私聊,聊天程序还需要提供群组功能,用户可以创建群组并邀请好友加入。
在群组中,用户可以发送群组消息、管理群组成员等。
2.5 数据存储和同步为了保证用户聊天记录的安全性和可靠性,聊天程序需要提供数据存储和同步功能。
用户的聊天记录需要存储在服务器上,并能够实时同步到用户的设备上。
3. 技术实现3.1 前端前端部分使用、CSS和JavaScript等技术来实现。
利用和CSS 创建用户界面,通过JavaScript实现与服务器的通信和数据处理等功能。
3.2 后端后端部分使用一种服务器端编程语言来实现,如Java、等。
利用后端语言来处理各种业务逻辑,包括用户注册、登录、好友管理、消息发送等。
3.3 数据库为了存储用户数据和聊天记录,聊天程序需要使用数据库来进行数据存储。
可以选择使用关系型数据库,如MySQL,或者使用NoSQL数据库,如MongoDB。
3.4 网络通信聊天程序需要使用网络通信来实现用户之间的消息传递。
可以使用常用的TCP/IP协议来进行通信,也可以使用更高层的协议,如HTTP或WebSocket等。
4.通过设计和实现一个类似于的聊天程序,我们可以提供给用户一个方便、高效的聊天工具,满足用户的即时通讯需求。
QQ聊天系统项目概要设计说明书第01版二○○九年六月版本控制信息目录概要设计说明书 (1)1范围 (5)1.1标识 (5)1.2系统概述 (5)1.3文档概述 (5)2引用文档 (5)3总体设计 (5)3.1需求规定 (5)3.2运行环境 (5)3.3基本设计概念和处理流程 (6)3.3.1前台处理流程 (6)3.3.2添加好友 (7)3.3.3信息修改 (8)3.3.1聊天模块 (9)3.4软件体系结构 (10)3.4.1用户层次功能模块图 (10)3.4.2服务器端层次功能模块图 (10)3.4.3后台数据库信息维护 (11)3.5系统子模块清单: (11)3.6功能需求与程序的关系 (12)3.7尚未解决的问题 (12)4接口设计 (12)4.1用户接口 (12)4.2外部接口 (15)4.3内部接口 (15)5运行设计 (16)5.1运行模块组合 (16)5.2运行控制 (16)5.3运行时间 (16)6系统数据结构设计 (16)6.1逻辑结构设计要点 (16)6.2物理结构设计要点 (17)6.3数据结构与程序的关系 (17)7系统出错处理设计 (17)7.1出错信息及补救措施 (17)7.1.1前台会员子系统出错信息和补救措施 (17)7.1.2服务器端出错信息和补救措施 (18)7.1.2其它出错信息及补救措施 (18)7.2系统维护设计 (18)1范围1.1标识QQ聊天系统概要设计说明书(QQS)1.2系统概述➢系统名称:QQ网络聊天系统(QQS)➢QQ聊天系统为用户网络聊天交流信息提供一个方便的电子平台。
该系统分用户员注册信息部分和后台系统管理部分。
➢用户通过向服务器提交信息,在数据库中写入相应的数据。
用户可以根据好友的QQ 号码或者是昵称来添加好友,而后选中该好友之后进行聊天功能。
如果对方没有在线,则将内容保存在服务器上,等用户上线之后传送信息。
➢用户可以对自己的信息进行维护和修改,服务器通过对用户的权限进行验证,修改对应的信息。
毕业设计(论文)报告用纸 第 1 页 共 11页 3.2 类库的设计 在本局域网聊天软件中,因为在后台服务器端的用户信息管理平台以及前台的客户端的登录窗口、主界面窗口以及聊天窗口都需要用到UDP协议。所以本程序中,将UDP协议封装成了一个控件,主要是为了便于客户端和服务器端的调用,并且将UDP控件和自定义类存储在了Controls文件夹中。当需要使用到UDP协议的时候,只需要在相应的窗口中加入SockUDP控件,然后设置SockUDP控件的相关的属性即可。下面对Controls中的SockUDP控件和其他的类分别进行说明。 (1)SockUDP控件 该控件主要是将UDP协议中的IP地址和端口号以及开启或者关闭的状态以控件的形式进行设置,并自定义一个了DataArrival事件,用于对主机的端口号进行监听,以获取远程计算机发送过来的消息。 在自定义控件上制作了System.Net.IPEndPoint 类的server属性,来获得对方IP地址和端口号信息 UDPSocket控件中包含CloseSocket()方法分别用于关闭UDP协议端口的监听功能,并在监听关闭的同时关闭用于接收信息的子线程。 Listener()方法用于实现主机端口号的监听功能,主要是将IP地址和端口号以网络端点进行存储,然后创建一个新的端口号,再设置接收缓冲区和发送缓冲区的大小。此外,还创建了一个线程,主要是用于获取当前接收到的信息,就是将获取的远程信息转换成二进制流。在线程打开时,将GetUDPData()方法所接收的信息传递给线程的委托。 GetUDPData()方法是在获取远程消息时,将消息转发给UDPSocket控件的DataArrival事件,可以通过该事件将消息发送给远程客户端。 Send()方法用于将主机获取的消息,通过IP地址和端口号发送给远程客户端。 Dispose()函数用以清理正在使用的资源 通过以上的方法,便制作完成了一个SockUDP控件。
(2)Publec_Class类 该类用于记录服务器端和客户端的基本信息,并通过自定义的方法MyHostIP()获取服务器端的所有IP地址,通过自定义方法Get_Windows()获取Windows目录。 (3)ClassForms类 该类将获取的的窗体在InnerList列表中进行添加和移除操作,在列表中查找相应的窗体。 (4)ClassMsg类 该类主要是用枚举型的元素指定消息发送的命令、消息类型、消息发送的状态等。其中,发送的消息命令包括了用户登录、用户登录结束上线、用户列表、打开语音、关闭语音、下线等命令;发送的消息类型包括了无类型、发送命令、发送消息、发送文件毕业设计(论文)报告用纸 第 2 页 共 11页 等。此外,该类还用来记录发送方和接收方的发送编号、IP地址以及端口号等信息,还记录了用户注册的用户名和密码等信息。 (6)ClassSerializers 类 ① SerializeBinary()方法 该方法是在客户端发送信息时,将发送的对象序列化为二进制流,并返回序列化的二进制流,因为Socket只能以二进制流的形式进行传输。 ② DeSerializeBinary()方法 该方法是在客户端接收信息时,将二进制流反序列化为对象,并返回反序列化后的对象,这样,便于在指定的控件上显示接收的信息。 (7)ClassUserInfo类 该类用于记录当前用户的编号、IP地址、端口号、用户名称和用户状态。 (8)ClassUsers 类 该类主要是将服务器端所有注册的用户信息存储到base类的InnerList列表中。这样,当用户注册或登陆时,可以将该列表中的信息发给当前在线的所有用户,以改变主窗体的显示情况。 ClassTextMsg类 该类主要是用枚举型的元素指定发送文本的字体、颜色、内容等。
4.2.2客户端登陆模块技术分析 在UDP协议的监听事件中通过开启一个线程,来实现局域网信息的发送和接收。要想创建一个子线程,需要实例化一个Thread类型的对象。子线程创建完后,可以使用线程的Start()方法开启当前线程。当子线程使用完之后,可以使用Thread对象的Sleep(0)方法将主线程睡眠,然后调用线程的trd.Abort()方法终止当前线程。 4.2.3客户端登陆模块实现过程 (1)新建一个Windows窗体,命名为FormLogon.cs。该窗体主要实现客户端的登陆功能。 (3)在登陆窗体加载时,获取服务器IP和端口号,再根据该IP地址和端口号与服务器建立通信,把用户的信息发送给服务器进行记录。 (4)在自定义控件SocUDP的DataArrival事件中,利用托管调用DataArrival事件,并在该控件的线程上,用指定的参数对其进行异步托管。 (5)托管对DataArrival事件进行异步执行,用于获取服务器端所返回的消息,当返回的是登陆成功消息时,存储服务器端返回的ID值进入客户端主窗体。 4.3 客户端主窗体模块设计 4.3.1客户端主窗体模块概述 主窗体模块主要显示当前已登陆的所有用户的名称,并根据用户的在线情况,设置毕业设计(论文)报告用纸 第 3 页 共 11页 用户名称前的图标样式。 4.3.2客户端主窗体模块技术分析 在本窗体中使用InnerList列表记录当前登陆用户的信息,并将InnerList列表中的信息添加到treeview控件中。treevie1控件上同级节点的连接线已经去掉,这样使各个图标看起来更加的美观。InnerList用于存储项目的ArrayList对象,它是CollectionBase对象中的一个属性,可以通过该属性的Add()和Remove()方法向列表中添加和移除元素。具有在线和离线的功能。当用户在线时,就显示图标,当用户下线时,就移去改图标。当下线时,UDP协议将关闭监听。 4.3.3客户端QQ模块实现过程 (1)新建一个Windows应用程序,将默认创建的Windows窗体命名为FormMain.cs, (2)在窗体加载时,首先要调用登陆窗体,当登陆窗体验证成功后,发送消息给服务器端,返回所有注册的用户信息。然后再根据用户的在线和离线状态,在Treeview上设置用户的图标。 (3)自定义方法DataArrival(),处理各类信息
case 0://有用户离线 userSingnOut(msg.ID );//处理用户离线 break; case 1://服务器告诉自己已经登录,登录过程 SuccessLogin(msg); break; case 2://服务器告诉用户自己目前在线 updateSelfState();//更新当前用户在线状态 break; case 3://服务器告诉用户有新的联系人登录 NewUserLogin(new ClassSerializers().DeSerializeBinary((new System.IO.MemoryStream(msg.MsgContent ))) as ClassUserInfo );//添加新登录的用户资料 break; case 4://收到用户部分联系人的资料 UsersDataArrival((new ClassSerializers().DeSerializeBinary((new System.IO.MemoryStream(msg.MsgContent ))) as Controls.ClassUsers));//收到用户所有联系人的资料 break; case 5://收到用户联系人发送来的对话消息 UserChatArrival(msg,Ip,Port);//处理对话消息 break; case 6://联系人返回已经收到刚才发送的对话消息 returnChatArrival(msg.ID );//联系人返回已经收到刚才发送的对话消息 break; 毕业设计(论文)报告用纸 第 4 页 共 11页 case 8://对方要求UDP打洞 UDPNatTranslators(msg,Ip,Port); break; case 10://收到联系人发出发送文件请求 sendFileRequest(msg,Ip,Port); break; case 11://收到联系人发送来的gif图片流 UserGifArrival(msg,Ip,Port);//处理gif图片消息 break; case 12://收到用户发送来的文本消息 UserTextChatArrival(msg,Ip,Port);//处理用户发送来的文本消息 break; case 13://收到语音对话请求 //MessageBox.Show("语音对话请求"+ Ip.ToString() +":"+ Port.ToString()); UserAVRequestArrival(msg,Ip,Port); break; case 14://对方告诉自己开始语音对话 //MessageBox.Show("开始视频对话"+ Ip.ToString() +":"+ Port.ToString()); UserBeginAV(msg,Ip,Port); break; case 15://对方已经取消息语音对话 CancelAV(msg.ID );//取消语音对话 break;
(10)当在用户头像上双击某一个在线用户的图标时,即可打开该用户的聊天窗口。然后在文本框输入文本信息发送,就可以与该用户进行文本信息的聊天。点击该窗口上的语音和文件传输的按钮,还可以与该用户进行点对点的语音和文件传输。 4.4 客户端消息发送模块设计 4.4.1客户端消息发送模块概述 消息发送模块主要用于实现客户端与远程客户端的消息通信。不但具有具有文本聊天的功能,还具有点对点的语音和文件传输等功能,此外,还可以进行字体的设置,表情的发送以及图片的发送等功能。 发送消息窗体名称FormSendMsg 定义的方法 private void trtFontSet_Click(object sender, System.EventArgs e)字体设置 private void butFontColor_Click(object sender, System.EventArgs e)字体颜色设置