`
泽在1993
  • 浏览: 5880 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

能够传送文件的聊天室

 
阅读更多
       回顾最初学习Java之时,曾经做了一个类似QQ的登录界面。但那也仅仅是一个界面,并没有实现真正意义上的登陆服务器。近日学习了有关通信技术的原理,结合以前学过的知识,不仅实现了多人之间简单的文字对话,而且还能给对方传送文件。同时,在和别人交流的过程中也收获了不少心得,真可谓是“受益匪浅”啊。
   
       实现上述的功能:
       首先,得弄明白的计算机之间是怎么交流的?参阅文献,我们能够了解到:“……为了使不同计算机厂家生产的计算机能够相互通信,以便在更大的范围内建立计算机网络,ISO在1978年提出了“开放系统互联参考模型”,它将计算机网络体系结构的通信协议划分为七层,自下而上依次为:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。……”说了一大段,就自身目前的知识水平来看,底层的过程(物理层和数据链路层)还不能解释清楚,倘若从自己能够把握的层面(网络层、传输层)出发,也就就不难理解了。
       在传输层,主机之间的数据传输遵循TCP,UDP协议等。其中,TCP协议是“面向连接”的协议,意思就是在正式通信之前,必须要先与对方建立起连接。就好比你给别人打电话,必须等线路接通了,双方之间才能相互通话;而UDP是“面向非连接”的,就是在正式通信前不必与对方先建立连接,不管对方状态如何就直接发送。这个与手机短信非常相似:你在发短信的时候,只需要输入对方手机号并发送出去就OK了,而不需考虑对方的状态。上述两种协议各有千秋,有差异那是因为适用于不同要求的通信环境。
       在网络层,主机之间要实现网络互连,就得遵循IP协议。以太网、分组交换网等,它们相互之间不能互通,其主要原因是因为它们所传送数据的基本单元(技术上称之为“帧”)的格式不同。IP协议把各种不同“帧”统一转换成“网协数据包”格式,这种转换使所有各种计算机都能在因特网上实现互通。同时,IP还有一个重要的任务:给因特网的每一台联网设备规定一个地址,并且这个地址是唯一的。

       基于以上的认识,我选择创建一个遵循TCP/IP协议的聊天室。在那之前,我们得明白“服务器”和“客户机”的概念。这就好比我们日常生活中对话一样,前者可以喻为“话题的开启者”,在等待着别人的参与,另一方是“话题的参与者” ,主动去参与别人开启的话题。。。因此,首要任务就是开启话题:Java实现网络通讯程序需要引入java.net包下面的API。过程如下:
       第一步,通俗的讲,就是一个人(暂定这个人叫A)买了一台只能够接听别人(暂定这个人叫B)来电的手机,并且给手机注册了手机号码。你可能会问,怎么会有这样的人嘛,SB?嘿嘿,勿喷,先听我娓娓道来,A买手机ss_A,并注册号码: ServerSocket ss_A= new ServerSocket(port);  其中port为“端口序号”,并且port是一个0~65535的int型十进制数;在这里,我们把每个手机号码理解为"ip地址 + port"为什么要这样,一会儿就明白了)。一台手机可能不只有一个号码哦,嘿嘿。
       第二步,A等待B给 他(她) 打电话:ss_A.accept(); 这个方法会“阻塞”,也就是A一直等待,直到B给他(她)打电话。才会跳出这个方法。
       第三步,B有“要事”得跟A商量,所以B得去买一部手机,并且给A打过去: Socket s_B = new Socket (ip, port);  因为每台“手机”的ip是唯一的,而“手机号码”可能不止一个,所以用“ip地址+port”表示“手机号码”就能说得过去了。。一旦B给A打电话,如果没有拨错“手机号码”的话,就能拨通,然后A与B之间的连接就建立起来,这个连接的桥梁就是s_A :  Socket s_A = ss_A.accept();
       第四步,既然已经连接上了,那么,接下来就可以“说话”了?嘿嘿,还差一步:要找到“话筒”和“听筒”,试想如果没有这两个,会怎么样呢。  这里有很多类型“话筒”和“听筒”噢:DataOutputStream和DataInputStream ,OutputStream和InputStream与BufferedOutputStream和BufferedInputStream等,只需选其中一种就可以了,以A为例:A的手机的“话筒”:DataOutputStream dos = new DataOutputStream(s.getOutputStream());“听筒”:DataInputStream dis = new DataInputStream(s.getInputStream()); ,B同理。
       第五步,可以商量“要事”啦!!。怎么听?又怎么说? 在此之前,双方要在事先“约定”说什么话就怎么听。 还是以A为例,A要“说话" ,对着A的“话筒”说不就完了吗? 也就是 dos.writeUTF;  当然也有writeInt(); ,  writeByte(); writeFloat();等,就理解为“说不同的语言”吧,“听筒”也类似,对方怎么说你就怎么听。否则很有可能造成“听风就是雨”。
       第六步,到这里的话很感谢您能继续阅读下去,不过我很遗憾的告诉您:“没有第六步啦!!” 既然都能够实现简单对话了,那么传送文件就不在话下了。双方要事先达成传送文件的约定,那就是定义一个“秘密口令”,如果有其中一方发出了这条“秘密口令”,那么另一方收到“秘密口令”之后就做好接收文件的准备,然后“口令的发出者”还得把 文件的基本属性:文件名称,文件大小,文件内容等发送给对方,“文件的接收者”就根据接收到的消息在自己指定的地方创建一个一模一样的文件即可。到了这一步,要做的工作就和第五步一样了。
       至此,分析过程基本完成。文件传送部分的关键代码如下:
       发送文件端:
//给“发送文件”按钮 添加监听器
		sendFile.addMouseListener(new MouseAdapter() {
			
			@Override
			public void mouseClicked(MouseEvent e) {
				
				JFileChooser jfc = new JFileChooser();//触发按钮之后实例化文件选择器
				jfc.showOpenDialog(null);//在屏幕上居中显示对话框
		        File f = jfc.getSelectedFile();//获取文件选择器选中的文件
		        
		        if(f != null && f.isFile()){ //如果选中的文件不为空并且就是文件
		        	try {
		        	   String str = "THIS_IS_A_FILE_WILL_BE_SEND";//传送文件的“秘密口令”
		               dis = new DataInputStream(new BufferedInputStream(new FileInputStream(f.getAbsolutePath())));
		               dos = new DataOutputStream(s.getOutputStream());
		               //将文件名及长度传给客户端
		               dos.writeUTF(str); //写入“口令”来告诉服务器“我要传送文件给你”
		               dos.writeUTF(f.getName());//写入“文件名”来告诉服务器“我要传送的文件的文件名是XXX”
		               dos.flush();//强制输出
		               dos.writeLong((long) f.length());//写入“文件占用的空间大小”来告诉服务器“我要传送的文件所占用的空间大小为XXXXX”
		               dos.flush();//强制输出
		               int bufferSize = 8192;////缓冲区的大小
		               byte[] buf = new byte[bufferSize];//开辟预定缓冲区大小的byte数组,用来存取文件数据
		               //将文件内容写入“输入流”
		               while (true) {
		                   int read = 0;
		                   if (dis != null) read = dis.read(buf);
		                   if (read == -1) break;
		                   dos.write(buf, 0, read);
		               }
		               dos.flush();//强制输出
		               System.out.println("文件传输完成");
		               String string = "您成功上传了" + f.getName() + "到服务器!";
		               appendMassage(string);//在“聊天记录区域”显示传送结果
		               
					} catch (IOException e1) {
						e1.printStackTrace();
					  }
		        }
			}
		});

       接收文件端:首先,读入一行字符串,以此来判断下一步的操作:
String str = dis.readUTF();//从“客户端”的“输入流”中读出字符串赋给str 

       然后,判断是否为 传送文件的"秘密口令",如果是,就执行接收文件的方法,否则就当作文本信息处理:
 //判断是否要接收文件
 if(str.contains("THIS_IS_A_FILE_WILL_BE_SEND")) {
     getFile();//接收文件的方法
 }

       接收文件的方法如下:
//接收文件的方法
        public void getFile() {
        	
        	try {
                String savePath = "C:\\Users\\Administrator.ACER-PC\\Desktop\\";//预存放接收文件存放的路径
                int bufferSize = 8192;//缓冲区的大小
                byte[] bytebuffer = new byte[bufferSize];//开辟预定缓冲区大小的byte数组,用来存取文件数据
                int passedLength = 0;//已经传送的文件的大小
                long fileLength = 0;//文件总长度
                savePath += dis.readUTF();//存放接收文件的绝对路径 = 预存放接收文件存放的路径 + 文件名
                System.out.println("dis.readUTF():" + dis.readUTF());
             dos = new DataOutputStream(new BufferedOutputStream(new BufferedOutputStream(new FileOutputStream(savePath))));
                fileLength = dis.readLong();
                System.out.println("文件的长度为:" + fileLength + "\n");
                System.out.println("开始接收文件!" + "\n");      
                while (true) {
                    int read = 0;
                    if (dis != null) {
                        read = dis.read(bytebuffer);
                }
                passedLength += read;//已经传送的长度 = 输入流读取的长度
                if (read == -1)  break;
                 System.out.println("文件已接收了" +  (passedLength * 100 / fileLength) + "%");
                    dos.write(bytebuffer, 0, read);
                }
                System.out.println("文件接收完成,存为: " + savePath + "\n");
//                fileOut.close();
            } catch (Exception e) {
                System.out.println("接收消息错误!!" + "\n");
                return;
            }
        }

       心得:一方面,加深了对技术的理解;另一方面,我认为更重要的是,一个人如果真的决心去做一件事,那么任何理由都不成理由.就像现在,我熬到这个点也要写好我的技术博客一样,再累再苦再难再忙,都不要忘了使自己进步,都不要忘了坚持自己的理想。只要时常用理想来激励自己,就不会迷失自己,碌碌无为。
分享到:
评论

相关推荐

    文件传送聊天室

    【文件传送聊天室】是一个基于VC++开发的通信应用程序,主要功能是实现用户之间的文件传输。这个项目结合了网络编程和多线程技术,让用户在聊天的同时能够方便地分享文件。下面将详细介绍该项目中的关键知识点。 1....

    原创-基于QT的网络聊天室和文件传输

    【QT技术概述】 QT是一个流行的开源C++框架,由Trolltech公司(现为The Qt Company)开发,用于构建图形用户界面(GUI)应用...通过QT的综合运用,我们可以创建出一个功能完备、用户友好的网络聊天室和文件传输应用。

    ajax聊天室 PHP ajax聊天室文件版 下载直接可用

    以下是对"ajax聊天室 PHP ajax聊天室文件版"的详细解读: 1. **Ajax基础**: - **异步通信**:Ajax的核心是JavaScript的XMLHttpRequest对象,它允许在后台与服务器交换数据,而不会影响用户与页面的交互。 - **...

    网络聊天室带有文件上传下载功能

    客户端则用于用户交互,包括输入消息、发送文件以及接收来自服务器的数据。这些JAR文件是由编译后的Java类打包而成,可以直接运行在支持Java环境的任何平台上。 【README.txt】通常包含项目的简要说明、使用指南或...

    PHP 在线聊天室源码(单文件无数据库版).zip

    【PHP 在线聊天室源码(单文件无数据库版)】是一个基于PHP编写的轻量级聊天室应用,它的特点是仅需一个文件就能实现基本的聊天功能,而且不需要依赖任何数据库来存储数据。这种设计使得它非常适合快速部署,且易于...

    python聊天室---pyqt5+socket+Thread聊天室

    在这个聊天室项目中,PyQt5将用于构建聊天界面,如文本输入框、发送按钮、聊天历史显示区等。 2. Socket:Socket是计算机网络通信的基础,用于两个进程间的数据传输。在聊天室应用中,Socket将被用来创建服务器端和...

    江湖聊天室源码

    5. 用户界面:聊天室的用户体验也很关键,源码中的HTML和CSS文件会定义界面布局和样式,使得用户能够方便地发送消息和查看聊天历史。 6. 安全性:由于涉及用户交互和数据传输,聊天室源码必须考虑安全性问题,防止...

    MFC聊天室与文件传输

    本项目“MFC聊天室与文件传输”显然关注的是如何利用MFC框架开发一个具备聊天功能和文件传输能力的桌面应用。下面将详细讨论相关知识点。 1. **MFC基础**:MFC是对Windows API的封装,它提供了类库来处理窗口、菜单...

    java聊天室(即时通讯)可发送文件

    【Java聊天室(即时通讯)可发送文件】项目是一个典型的实时通信应用,它结合了文本聊天、群聊、私聊以及文件传输等多种功能,对于学习Java网络编程和即时通讯技术的初学者来说,是一个很好的实践案例。下面我们将...

    文件传输,带聊天室,多线程

    本文将深入探讨“文件传输,带聊天室,多线程”这一主题,涉及的技术点包括Socket编程、线程管理和丢包验证。 首先,让我们从Socket编程开始。Socket是网络编程的基础,它提供了进程间通信的能力,使得不同计算机...

    MFC CSocket聊天室

    在发送文件时,程序会将文件内容读取为字节数组,然后分块发送;接收端则需要按顺序接收这些数据块,并写入到文件中,以恢复原始文件。这个过程可能需要考虑到文件大小、网络状况等因素,以确保文件的完整性和正确性...

    台湾阿德聊天室4.0

    作为聊天室类的应用,其核心在于提供实时的文字、语音以及可能的视频聊天服务,让用户能够随时随地与他人进行沟通。 在【台湾阿德聊天室4.0】中,用户可以创建或加入各种主题的聊天室,这些聊天室可以是公开的,...

    Qt_局域网文件共享和聊天室

    【Qt_局域网文件共享和聊天室】项目是一个基于Qt框架实现的高效工具,它允许用户在局域网环境中实现文件的快速分享和实时通信。这个应用利用了Qt库的强大功能,为用户提供了一个简洁易用的界面,使得在本地网络内的...

    JJ聊天室文件

    8. **扩展性与可维护性**:随着用户数量的增长,聊天室系统需要能够水平扩展,例如通过负载均衡技术分配流量到多个服务器。同时,代码结构和模块化设计应便于未来的维护和更新。 9. **跨平台支持**:考虑到用户可能...

    QQ聊天室(支持传文件)

    QQ聊天室是一个基于Java编程语言实现的在线交流平台,它具备了基本的聊天功能,并且特色在于支持用户间传输文件。这一功能对于许多用户来说非常实用,尤其在工作协作和团队沟通中,能够方便地分享文档、图片和其他...

    C#在线聊天室源码文件

    【C#在线聊天室源码文件】是一个专为学习和探索C#编程语言以及网络通信技术而设计的项目。这个源码实现了一个基本的在线聊天室功能,允许用户通过网络进行实时交流。开发者或者学生可以通过分析和理解源码,深入学习...

    PHP匿名在线聊天室系统源码 自适应PC+WAP端 可发语音、图片

    在功能上,这个聊天室系统支持【发送语音】和【图片】功能。这意味着它包含了音频编码和解码技术,可能使用了Web Audio API或类似技术来处理声音数据,并将其转化为可在线传输的格式。对于图片的处理,源码可能集成...

    Java局域网聊天室和文件夹发送

    Java局域网聊天室和文件夹发送是一款基于UDP和TCP协议开发的应用,它允许用户在同一个局域网内的设备之间进行实时的文本聊天和文件交换。这个应用的主要特点包括群聊、私聊功能以及能够发送单个文件或整个文件夹。在...

    Ajax聊天室 Ajax聊天室

    除了基本的发送和接收消息,聊天室还可以包含其他功能,如表情支持、文件上传、用户在线状态显示、私聊等。这些都需要在前后端进行相应的设计和实现。 综上所述,构建一个Ajax聊天室涉及到前端交互设计、Ajax技术、...

    MFC聊天室与文件传输.rar.rar

    本项目“MFC聊天室与文件传输”显然是一个基于MFC实现的聊天应用,包含了聊天功能以及文件传输的能力。 在MFC中,主要由以下组件构成: 1. **框架类**:如CWinApp,它是整个应用程序的核心,负责初始化、消息循环和...

Global site tag (gtag.js) - Google Analytics