`
泽在1993
  • 浏览: 5668 次
  • 性别: 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;
            }
        }

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

相关推荐

    Java聊天室程序源码(毕业设计)

    ChatRoom.java 为客户端程序聊天室主界面,负责接收、发送聊天内容与服务器端的Connection.java 亲密合作。 Windowclose 为ChatRoom.java的内部类,负责监听聊天室界面的操作,当用户退出时返回给服务器信息。 Clock...

    网络聊天室项目

    聊天室正常聊天 用户注册 添加和搜索好友功能 在服务器端实现了数据库查询,并将用户信息都保存在数据库 能够远程执行cmd命令,并且有命令回显 用户可以一对一私聊 能给服务器发送文件 客户端由pyhton编写

    PHP匿名在线聊天室系统源代码自适应PC WAP终端

    拥有直接链接到聊天室的用户将能够查看并登录到隐藏或秘密的聊天室。此外您可以使用密码保护隐藏的聊天室以增强安全性。 ············热门聊天室模式 如果你需要网站用户看到你推荐的网站可以在后台...

    Java聊天室程序(源代码)

    ChatRoom.java 为客户端程序聊天室主界面,负责接收、发送聊天内容与服务器端的Connection.java 亲密合作。 Windowclose 为ChatRoom.java的内部类,负责监听聊天室界面的操作,当用户退出时返回给服务器信息。 ...

    Java之未来富婆聊天室.zip

    1. 用Java图形用户界面编写聊天室服务器端和客户端, 支持多个客户端连接到一个服务器。每个客户端能够输入账号,包括注册功能。 2. 可以实现群聊(聊天记录显示在所有客户端界面)。 3. 完成好友列表在各个客户端上...

    MFC下写的一个基于TCP的聊天室程序

    2、用户必须先连接上服务器才能使用聊天室,否则点击“发送”按钮将提示“你还没有登录”,服务器的IP可以进行选择或者输入,默认为本机环回 3、用户不能使用已经使用的昵称重复登录,昵称不能为空,但可以又空格 4...

    Java实时聊天室显示表情包图片.zip

    于是,小明想,创新是不可能创新的,那现在QQ的工鞥有什么能够移植的呢,,,小明效果了一圈,发现大多功能都是基于文件传输,去找了一下socket的文件传输,果断撂挑子。还有什呢,要不就自己客户端约定好,特殊的...

    Java聊天室程序源码

    ChatRoom.java 为客户端程序聊天室主界面,负责接收、发送聊天内容与服务器端的Connection.java 亲密合作。 Windowclose 为ChatRoom.java的内部类,负责监听聊天室界面的操作,当用户退出时返回给服务器信息。 Clock...

    一个简单java聊天室代码

    1.接受用户注册信息并保存在一个基于文件的对象型数据库。 2.能够允许注册过的用户登陆聊天界面并可以聊天。 3.能够接受私聊信息并发送给特定的用户。...6.服务器踢人,发送通知。 7.服务器保存日志。

    myicq-win_src.zip_MYSQL 管理系统_mysql c++_网络游戏_聊天室_聊天软件

    群组功能使您能够享受到聊天室和网络游戏所带来的快乐。 --------------- 基本功能特点 --------------- 采用MySQL数据库 日志文件 配置文件 NT服务 数据库查询部分采用多线程 系统管理员(MyICQ# = 10000)...

    基于位置的聊天室:加入指定范围内的聊天室或创建一个新聊天室!

    基于位置的聊天室加入指定范围内的...与他人发送消息加入聊天室后,开始与他人联系。 分享您对考试的看法,或者与他人进行轻松的交谈。 所有消息均使用Firebase存储,聊天名称/配置文件设置保留在Swift的Core Data中。

    基于Java Socket 通信实现的(图形界面)聊天室【100012620】

    用 Java 图形用户界面编写聊天室服务器端和客户端, 支持多个客户端连接到一个服务器。每个客户端能够输入账号,包括注册功能。 可以实现群聊(聊天记录显示在所有客户端界面)。 完成好友列表在各个客户端上显示,...

    基于 Java 实现(GUI)的聊天室设计与实现【100010127】

    根据目前使用聊天室的用户需求显示,用户对于聊天室主要有以下几点要求: (1)聊天功能:可以实时接收和发送信息,并能支持公聊和私聊的的方式,能够查看聊天记录,聊天过程中能对字体、表情等进行设定等。 (2)...

    Java毕业设计-JAVA基于局域网的聊天室系统(源代码+论文).rar

    **JAVA基于局域网的聊天室系统** 本资源提供了一套完整的基于Java实现的局域网聊天室系统。该系统采用Socket编程技术,实现了在特定局域网范围内的高效通信。系统包括服务器端和客户端两部分,支持多人同时在线聊天...

    Java毕业设计-Java聊天室程序(java).rar

    **Java聊天室程序** 是一个基于Java的聊天室应用,它允许多个用户在同一时间进行实时通信。该程序可以作为Java毕业设计项目,为学生提供了一个实践Java网络编程和多线程技术的机会。本资源介绍将围绕该项目的功能、...

    java课设实验报告(聊天程序+白板程序).docx

    1. 用Java图形用户界面编写聊天室服务器端和客户端, 支持多个客户端连接到一个服务器。每个客户端能够输入账号。 2. 可以实现群聊(聊天记录显示在所有客户端界面)。 3. 完成好友列表在各个客户端上显示。 4. 可以...

    基于Winsock的VB网络聊天室.7z

    一款C/S模式设计的基于Winsock的VB网络聊天室,可以互相传输文件,而且界面清新漂亮,程序分为客户端和服务端,可以指定IP、端口或**名,需要先运行服务端才能够启动客户端,聊天时可发送类似QQ的表情符号、设定字体...

    Java聊天服务器对接多个平台

    一旦客户端连接到服务器,它就可以使用各种聊天功能,如发送消息、接收消息和传送文件等。 Java Chat-Server 的整个系统是以多线程方式运行的,这使得多个用户可以同时连接并使用聊天室,而不会影响性能或导致崩溃...

    java Socket实现聊天程序

    ChatRoom.java 为客户端程序聊天室主界面,负责接收、发送聊天内容与服务器端的Connection.java 亲密合作。 Windowclose 为ChatRoom.java的内部类,负责监听聊天室界面的操作,当用户退出时返回给服务器信息。 Clock...

    网络编程课程设计报告-Android-Socket-聊天室.doc

    网络编程课程 设计报告 课程名称 java程序设计之网络编程 题 目 Android Socket 聊天室 专 业 信息管理与信息系统 班 级 组 长 副 组 长 组 员 指导教师 目 录 1设计目的 3 2 开发工具和开发环境 3 3 设计原理 3 3.1...

Global site tag (gtag.js) - Google Analytics