网络编程课程设计java聊天室.docx
- 文档编号:4370850
- 上传时间:2022-12-01
- 格式:DOCX
- 页数:24
- 大小:56.41KB
网络编程课程设计java聊天室.docx
《网络编程课程设计java聊天室.docx》由会员分享,可在线阅读,更多相关《网络编程课程设计java聊天室.docx(24页珍藏版)》请在冰豆网上搜索。
网络编程课程设计java聊天室
网络编程课程设计报告
题目:
简单聊天室设计
院系:
专业班级:
学号:
学生姓名:
指导教师:
2016年1月6日
1.引言
1)本课题的来源
随着网络普及和上网人数的大增,在国内各大门户网站都架设了大型聊天室。
如:
新浪聊天室、中华网社区聊天室、搜狐等都成为网民们的热门聊天室。
以新浪聊天室为例看,聊天室呈现积聚人气作用,并开设不同主题的聊天室以使网民们具有针对性的使用聊天室。
本人计划设计一个实现基于Java语言的聊天室的Windows网络编程,启动服务器后,客户端运行,向服务器端发出请求,连接成功后,会弹出一个聊天室的界面,该界面有私聊(可加入生动的表情描述)、群聊、发送文件等功能,客户可以根据自己的需要选择不同的功能。
具体任务是实现文件的接收功能,启动服务器监听后,接收客户端发来请求,安排线程接收对方发来的文件(例如文档、照片、音乐、电影等)并存入指定的文件夹中。
2)本系统涉及的知识点
1、套接字Socket的建立、连接、关闭,客户端和服务器端的输入/输出流的连接。
2、Java中的多线程及线程的常用方法、Runnable接口。
3、基于SWING的图形用户界面设计:
布局设计、文本组件、按钮与标签组件、列表组件等。
4、InetAddress类。
5、输入/输出流:
文件、文件字节流、文件字符流、缓冲流、数据流。
3)功能要求
(1)在服务器端和客户端分别创建一个套接字对象,通过输入输出流连接在一起。
套接字调用close()方法关闭双方的套接字连接。
(2)使用多线程处理套接字连接,把服务器端或客户端读取的数据放在一个单独的线程中去进行,防止服务器端或客户端读取数据可能引起的堵塞。
服务器端收到一个客户的套接字后,应该启动一个专门为该客户服务的线程。
(3)成功连接后,在图形界面中用户可以根据自己的需要进行不同的操作,如:
群聊天、和某一个用户单独聊天(可加入生动的表情描述)、发送文件等。
在界面中会显示用户的聊天记录。
4)开发环境的选择
在进行开发之前,首先决定的第一个问题就是,该使用什么开发环境来编写该系统?
以目前常用的开发语言来讲有C/C++、.NET技术,JAVA、VisualBasic几种。
还有Eclipse,、BorlandJBuilder等,这些并不是程序语言,而是程序语言在建构程序时的“集成开发工具”,不过它们在开发设计的过程中也占有相当重要的角色,因为选用正确的集成开发工具,可以加速程序设计的进行、测试与排错,因而对整体进度具有决定性的影响。
基于以下几点,选择JAVA语言开发技术。
1、就执行平台而言,必须考虑的问题之一是用户可能使用的操作系统。
用户可能使用的是WindowsLinux。
JAVA语言具有平台无关性,可以不需要任何修改就可以运行在支持JAVA的任何计算机上。
2、JAVA的Swing组件开发技术可以开发丰富的图形界面,并且SwingAPI类提供了丰富的外部接口和方法,可以方便实现系统功能。
3、就项目开发而言,纯粹的面向对象,加上数量巨大的类所提供的方法(函数)库的支持,使得利用Java开发各种应用程序,可以说是易如反掌。
此外,在程序除错、修改、升级和增加新功能等方面,因其面向对象的特性,使得这些维护也变得非常容易。
4、Java支持内在的多线程运行,提供分布式的并发机制,运行效率高。
5、异常处理,为了使Java程式更稳定、更安全,Java引入了异常处理机制。
能够在程序中产生异常情况的地方,执行相对应的处理,不至于因突发或意外的错误造成执行中断或是死机。
通过这种异常处理,不仅能够清晰地掌握整个程序执行的流程,也使得程序的设计更为严谨。
6、高性能,Java可以在运行时直接将目标代码翻译成机器指令。
Sun用直接解释器一秒钟内可调用300,000个过程。
翻译目标代码的速度与C/C++的性能没什么区别。
7、网络功能,Java可以说是借助因特网而重获新生的,自然具备编写网络功能的程序。
不论是一般因特网/局域网的程序,如Socket、Email、基于Web服务器的Servlet、JSP程序,甚至连分布式网络程序,如CORBA、RMI等的支持也是非常丰富的,使用起来也很方便。
5)开发技术的选择
本课题选择了javaSocket技术开发网络聊天室。
什么是socket?
socket是一种用于表达两台机器之间连接“终端”的软件抽象。
对于一个给定的连接,在每台机器上都有一个socket,你可以想象一个虚拟的"管道"工作在两台机器之间,“管道”连在两台机器的socket上。
当然,物理硬件和两台机器之间的“管道”这些连接装置都是未知的,抽象的所有目的就是为了让我们不必了解更多的细节。
简单的说,一台计算机上的socket同另一台计算机通话创建一个通信信道,程序员可以用这个信道在两台机器之间发送数据。
当你发送数据时,TCP/IP协议栈的每一层都给你的数据里添加适当的报头。
有个好消息是java语言隐藏了所有这些细节,这也是为什么他们有时被叫做“流socket”。
思考一下socket像电话听筒一样在电话的任意一端--你和我通过一个专门的信道来进行通话和接听。
会话将一直进行下去直到我们决定挂断电话(除非我们使用蜂窝电话),除非我们挂断电话,否则我们各自的电话线路都会占线。
如果你需要在两台机器之间进行通讯而不使用高级机制像ORBs(以及CORBA,RMI,IIOP等等),socket比较适合你。
Socket的底层机制则相当棘手。
幸运的是,java平台给我们一些虽然简单但是相当强大的高层抽象以至于我们创建和使用socket更加容易一些。
一般而言,javasocket有下面两种类型:
•TCPsocket(由Socket类实现,下面的章节我们将对其讨论)
•UDPsocket(由DatagramSocket类实现)
TCP和UDP扮演同样的角色,但是实现是不同的。
两者都接收传输协议数据包并把它们传递到表示层。
TCP把信息分解成数据包(datagrams)并在接收端重新组装起来。
它还对丢失的数据包进行重新传输的请求。
TCP减少了上层的担忧。
UDP没有组装和重传请求的功能。
它只是传输数据包。
更高层的层必须确保信息的完整性以及组合顺序的正确性。
2.功能设计
1、Socketsocket=newSocket(Stringhost,intport);客户端创建Socket对象,host是服务器端的IP地址,port是一个端口号,该对象用于连接服务器。
2、BufferedReaderbr=newBufferedReader
(newInputStreamReader(socket.getInputStream())); 创建一个使用默认大小输入缓冲区的缓冲字符输入流。
该输入流的指向是一个Reader流,Reader流将数据读入缓冲区,BufferedReader再从缓冲区中读取数据。
InputStreamReader是字节流通向字符流的桥梁:
它使用指定的charset读取字节并将其解码为字符。
getInputStream()获取字节输入流。
3、PrintStreamps=newPrintStream(socket.getOutputStream());创建新的打印流,PrintStream为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。
它还提供其他两项功能。
与其他输出流不同,PrintStream永远不会抛出IOException;而是,异常情况仅设置可通过checkError方法测试的内部标志。
4、Filefile=getFile();调用getFile()函数返回一个file的的路径,提示用户输入一个路径,判断是否存在该文件,如果输入非法给予提示,重新输入。
5、ps.println(file.getName());ps.println(file.length());将文件名和大小发送到服务端。
6、Stringmsg=br.readLine();if("已存在".equals(msg)){}接收服务器发送回来的是否存在的结果.如果文件已存在,打印提示,客户端退出.如果不存在,准备开始上传。
7、longfinishLen=Long.parseLong(msg);服务器端文件的长度。
8、FileInputStreamfis=newFileInputStream(file);创建FileInputStream从文件中读取数据,OutputStreamout=socket.getOutputStream();输出字节流,输出流接收输出字节并将这些字节写出到Socket的输出流。
9、fis.skip(finishLen);从输入流中跳过并丢弃finishLen个字节的数据,即跳过服务端已完成的大小。
10、len=fis.read(byte[]buffer)); 从此输入流中将最多b.length个字节的数据读入一个byte数组中。
11、out.write(byte[] b,int off,int len)将指定byte数组中从偏移量off开始的len个字节写入此输出流。
3.聊天室界面
4.全部程序:
服务器端:
packagechat;
import.*;
importjava.io.*;
importjava.util.*;
publicclassChatServer{
publicstaticvoidmain(String[]args)throwsException{
ServerSocketsvSocket=null;
Vectorthreads=newVector();
try{
svSocket=newServerSocket(5555);
System.out.println("listening...");
}catch(Exceptionex){
System.out.println("ServercreateServerSocketfailed!
");
return;
}
try{
intnid=0;
while(true){
Socketsocket=svSocket.accept();
System.out.println("acceptaclient");
ServerThreadst=newServerThread(socket,threads);
st.setID(nid++);
threads.add(st);
newThread(st).start();
for(inti=0;i ServerThreadtemp=(ServerThread)threads.elementAt(i); } System.out.println("Listenagain..."); } }catch(Exceptionex){ System.out.println("serverisdown"); } } } classServerThreadimplementsRunnable{ privateVectorthreads; privateSocketsocket=null; privateDataInputStreamin=null; privateDataOutputStreamout=null; privateintnid; publicServerThread(Socketsocket,Vectorthreads){ this.socket=socket; this.threads=threads; try{ in=newDataInputStream(socket.getInputStream()); out=newDataOutputStream(socket.getOutputStream()); } catch(Exceptionex){ } } publicvoidrun(){ System.out.println("Threadisrunning"); try{ while(true){ Stringreceive=in.readUTF(); if(receive==null)return; //下线通知 if(receive.contains("黯然下线了")){ for(inti=0;i ServerThreadst=(ServerThread)threads.elementAt(i); st.write("***"+receive+"***"); } } //上线通知 elseif(receive.contains("上线了")){ for(inti=0;i ServerThreadst=(ServerThread)threads.elementAt(i); st.write("<"+getID()+">: "+receive); } } //作为服务器监听中 elseif(receive.contains("监听中")){ for(inti=0;i ServerThreadst=(ServerThread)threads.elementAt(i); st.write("***"+receive+"***"); } } //发送消息 elseif(receive.contains("说")){ //发送广播消息 if(receive.contains("大家")){ for(inti=0;i ServerThreadst=(ServerThread)threads.elementAt(i); st.write("<"+getID()+">: "+receive); } } //发送指定消息 else{ inttemp=receive.indexOf("<"); inttemp1=receive.indexOf(">"); //获得接收者ID号 StringtempS=receive.substring(temp+1,temp1); inti=Integer.parseInt(tempS); //指定接收者输出 ServerThreadst=(ServerThread)threads.elementAt(i); st.write("<"+getID()+">: "+receive); //发送者自己也输出 st=(ServerThread)threads.elementAt(getID()); st.write("<"+getID()+">: "+receive); } } else{ ServerThreadst=(ServerThread)threads.elementAt(getID()); st.write("***"+receive+"***"); } } }catch(Exceptionex){ threads.removeElement(this); ex.printStackTrace(); } try{ socket.close(); }catch(Exceptionex){ ex.printStackTrace(); } } publicvoidwrite(Stringmsg){ synchronized(out){ try{ out.writeUTF(msg); }catch(Exceptionex){ } } } publicintgetID(){ returnthis.nid; } publicvoidsetID(intnid){ this.nid=nid; } } 服务器端的文件传送: packagechat; importjava.io.BufferedReader; importjava.io.File; importjava.io.FileOutputStream; importjava.io.IOException; importjava.io.InputStream; importjava.io.InputStreamReader; importjava.io.PrintStream; import.ServerSocket; import.Socket; importjava.text.SimpleDateFormat; importjava.util.Date; importjavax.swing.JOptionPane; publicclassfilesendServer{ publicvoidfilereceive()throwsException{ //1.创建ServerSocket,在循环中接收客户端请求,每接收到一个请求就开启新线程处理 ServerSocketserverSocket=newServerSocket(1234); JOptionPane.showMessageDialog(null,"服务已启动,绑定1234端口! "); while(true){ Socketsocket=serverSocket.accept(); newfileServerThread(socket).start(); } } } classfileServerThreadextendsThread{ Socketsocket; publicfileServerThread(Socketsocket){ this.socket=socket; } publicvoidrun(){ FileOutputStreamfos=null; try{ //3.获取输入输出流 BufferedReaderbr=newBufferedReader(newInputStreamReader(socket.getInputStream())); PrintStreamps=newPrintStream(socket.getOutputStream()); //7.接收文件,查找是否存在.如果存在,给写一个消息给客户端,服务端线程结束.如果不存在,写消息给客户端,准备开始上传. StringfileName=br.readLine(); longfileLen=Long.parseLong(br.readLine()); Filedir=newFile("upload"); dir.mkdir(); Filefile=newFile(dir,fileName); if(file.exists()&&file.length()==fileLen){//文件已存在,length()即为文件大小,文件不存在length()为0 ps.println("已存在"); return; } else{ ps.println(file.length());//文件已存在,length()即为文件大小,文件不存在length()为0 } //10.从Socket的输入流中读取数据,创建FileOutputStream写出到文件中 Stringtime=newSimpleDateFormat("yyyy-MM-ddHH: mm: ss").format(newDate()); System.out.println(time+""+(file.exists()? "开始断点续传: ": "开始上传文件: ")+file.getName()); longstart=System.currentTimeMillis(); InputStreamin=socket.getInputStream(); fos=newFileOutputStream(file,true);//文件存在就追加,文件不存在则创建 byte[]buffer=newbyte[1024]; intlen; while((len=in.read(buffer))! =-1){//这个地方会堵塞,如果客服端没有关闭socket.服务器端读不到流末尾(-1) fos.write(buffer,0,len); if(file.length()==fileLen)//文件大小等于客户端文件大小时,代表上传完毕 break; } fos.close(); longend=System.currentTimeMillis(); time=newSimpleDateFormat("yyyy-MM-ddHH: mm: ss").format(newDate()); System.out.println(time+""+"上传文件结束: "+file.getName()+",耗时: "+(end-start)+"毫秒"); ps.println("上传成功"); socket.close(); }catch(IOExceptione){ if(fos! =null)
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 网络 编程 课程设计 java 聊天室