java实现TCP与UDP混合传输文件总结
最近在用java写基于UDP传输文件的网络,遇到了很多问题,也参考了很多人编写的程序,通过 自己的整理和设计,终于写完了自己程序,现在将在编程中遇到的问题总结一下。
发送方:
首先发送方需要发送文件的一些属性给文件接收方,如文件的名称,文件的大小等,让文件接收方判断是否接受文件,由于这部分内容比较重要,不能出现丢包的现象,所以采用TCP/IP协议来传输文件,而在文件传输的时候,我们采用UDP协议传输,这样能让文件传输得更快。先看一下发送方代码。
import java.awt.*; import java.io.*; import java.net.*; import java.util.*; import java.util.concurrent.TimeUnit; import javax.swing.*; public class FileClient extends JFrame { FileDialog fd1 = null; DatagramSocket ds = null; DatagramPacket sendDp = null; static int sendDataLen = 10240; public byte[] sendBuff = new byte[sendDataLen]; public InetAddress udpIP = null; static int udpPort = 10000; static int tcpPort = 9999; public static void main(String[] args) { // TODO Auto-generated method stub FileClient fc = new FileClient(); fc.fileSender(); } public void fileSender() { try { // 打开windows的文件对话框 fd1 = new FileDialog(this, "请选择需要打开的文件", FileDialog.LOAD); fd1.setVisible(true); String filePath = fd1.getDirectory() + fd1.getFile(); String location = filePath.replaceAll("\\\\", "/"); System.out.println("绝对文件目录+文件名" + filePath); System.out.println("绝对文件目录+文件名" + location); DataInputStream dis = new DataInputStream(new BufferedInputStream( new FileInputStream(location))); // 单位是字节 int fileLen = dis.available(); System.out.println("文件长度" + fileLen); // **************************************************** // 写一个TCP协议发送文件标题,让接受端确认是否接受 Socket s = new Socket("127.0.0.1", tcpPort);// 发送到本机 PrintWriter pw = new PrintWriter(s.getOutputStream(), true); String headInfo = fd1.getFile() + "/" + fileLen; pw.println(headInfo); // 等待对方确认 InputStreamReader isr = new InputStreamReader(s.getInputStream()); BufferedReader br = new BufferedReader(isr); // 阻塞等待 String info = br.readLine(); System.out.println("我接收到文件接收器给我返回的内容了=" + info); if (info.equals("YES")) { s.close(); System.out.println("我是文件发送器UDP,我已经开始发送了"); // 主机从任意空闲端口发送; ds = new DatagramSocket(); udpIP = InetAddress.getByName("127.0.0.1"); while (dis.read(sendBuff) > 0) { sendDp = new DatagramPacket(sendBuff, sendBuff.length, udpIP, udpPort); ds.send(sendDp); TimeUnit.MICROSECONDS.sleep(1);// 限制传输速度 // ****************************************** } } else { JOptionPane.showMessageDialog(null, "对方拒绝接受文件", "消息提示", JOptionPane.WARNING_MESSAGE); dis.close(); s.close(); } System.out.println("发送完毕"); dis.close(); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } }
接收方(有一个确认接对话框类):
package com.tcpip.model; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.*; import java.net.*; import javax.swing.*; public class FileReceiver { static final int receivePort = 10000; DatagramPacket receiveDp = null; DatagramSocket receiveDs = null; int dataLen = 10240; public byte[] inBuff = new byte[dataLen]; String filePath = null; InetAddress clientIp = null; String myUserId = "小富"; public static void main(String[] args) { // TODO Auto-generated method stub FileReceiver fr = new FileReceiver(); fr.fileReceiver(); } public void fileReceiver() { try { // 写一个TCP接收协议,判断是否接受对方发过来的信息 ServerSocket ss = new ServerSocket(9999); // 阻塞,等待接收 Socket s = ss.accept(); PrintWriter pw = new PrintWriter(s.getOutputStream(), true); // 读取客户端信息 InputStreamReader isr = new InputStreamReader(s.getInputStream()); BufferedReader br = new BufferedReader(isr); // 阻塞,等待接收从缓存中读取 String fileInfo = br.readLine(); String headInfomation[] = fileInfo.split("/"); String fileName = headInfomation[0]; String fileLen0 = headInfomation[1]; System.out.println("tcp接受到的内容为=" + headInfomation[0]); System.out.println("tcp接受到的内容为=" + headInfomation[1]); int fileLen = Integer.parseInt(fileLen0); // 显示面板,显示对方发过来的文件信息,文件名称及文件大小,并确定是否收文件 ReceiveConfirm rc = new ReceiveConfirm(myUserId, fileName, fileLen); String wait = rc.getLocationpath(); // 等待存储文件的路径的产生 while (wait.equals("wait")) { wait = rc.getLocationpath(); System.out.println("我在这儿等待接收存储方的文件目录"); } String headInfo = "YES"; pw.println(headInfo); ss.close(); String filePath = rc.getLocationpath(); System.out.println("保存文件到目录" + fileInfo); DataOutputStream fileOut = new DataOutputStream( new BufferedOutputStream(new FileOutputStream(filePath))); receiveDs = new DatagramSocket(receivePort); System.out.println("我是文件接收器1,我已经运行"); int times = fileLen / dataLen;// 循环接收的次数 int restSize = fileLen % dataLen;// 接收剩下的字节 for (int i = 0; i < times; i++) { System.out.println("服务器已启动"); receiveDp = new DatagramPacket(inBuff, inBuff.length); receiveDs.receive(receiveDp); fileOut.write(inBuff, 0, receiveDp.getLength()); fileOut.flush(); } // 接收最后剩下,在inBuffer中能存下。 if (restSize != 0) { System.out.println("我有剩余"); receiveDp = new DatagramPacket(inBuff, inBuff.length); receiveDs.receive(receiveDp); fileOut.write(inBuff, 0, receiveDp.getLength()); fileOut.flush(); fileOut.close(); } System.out.println("接收完毕" + fileLen); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); if (receiveDs != null) { // 关闭receiveDs的对象 receiveDs.close(); } JOptionPane.showMessageDialog(null, "发送信息异常,请确认10000(接收端)号端口空闲,且网络连接正常", "网络异常", JOptionPane.ERROR_MESSAGE); System.exit(1); } } } class ReceiveConfirm implements ActionListener { // dingyi JLabel jl; JButton jb1, jb2; JPanel jp1, jp2; String headInfo = null; String myUserId = null; int fileLen = 0; float result = 0f; JFrame jf = null; private static String locationpath = "wait"; public ReceiveConfirm(String myUserId, String headInfo, int fileLen) { jf = new JFrame(); this.headInfo = headInfo; this.myUserId = myUserId; this.fileLen = fileLen; result = fileLen / 1024; System.out.println(myUserId + headInfo); // 创建 jl = new JLabel(myUserId + " 发来文件:【 " + headInfo + " 】,文件大小" + result + "KB,是否接受"); jb1 = new JButton("是"); jb1.addActionListener(this); jb2 = new JButton("否"); jb2.addActionListener(this); jp1 = new JPanel(); jp2 = new JPanel(); // 布局管理设置 // 添加组件 jp1.add(jl); jp2.add(jb1); jp2.add(jb2); jf.add(jp1, "Center"); jf.add(jp2, "South"); // 设置属性 jf.setSize(500, 120); jf.setTitle("提示信息"); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jf.setVisible(true); jf.setLocation(550, 300); } @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub if (e.getSource() == jb1) { jf.dispose(); // FileDialogTest fdt=new FileDialogTest(); JFrame jf = new JFrame(); FileDialog fd = new FileDialog(jf, "选择保存文件路径", FileDialog.SAVE); fd.setVisible(true); System.out.println("保存位置" + fd.getDirectory() + fd.getFile()); String filePath = fd.getDirectory() + fd.getFile(); locationpath = filePath.replaceAll("\\\\", "/"); System.out.println("保存位置1" + locationpath); } } public String getLocationpath() { System.out.println("保存位置2" + locationpath); return locationpath; } }
相关推荐
总的来说,这个UDP/TCP聊天程序设计考虑到了网络通信的效率和可靠性,通过混合使用TCP和UDP,试图在保证基本消息传递可靠性的同时,实现更快的实时交互。同时,通过多线程处理,确保了程序的流畅运行。这为学习网络...
此外,还可以使用Java NIO(非阻塞I/O)来提升性能,或者结合TCP的可靠性和UDP的高效性,设计混合协议。 通过学习这些知识点,开发者能够理解如何在Java环境中利用UDP构建一个简单的聊天程序,并具备进一步优化和...
"udp聊天室 java,Python" 指出该聊天室的实现涉及两种编程语言:Java和Python。这意味着可能有两种不同实现或一个项目中混合使用了这两种语言。 【描述解析】 描述提到这个聊天室是“基于udp的”,意味着它使用了...
在这个教程中,我们将详细讲解如何在一个主设备和两个从设备之间有效地进行TCP/IP数据的传输与交换。 首先,我们要理解TCP/IP协议族的基本构成。TCP/IP模型通常被分为四层:应用层、传输层、网络层和数据链路层。...
与TCP(Transmission Control Protocol)不同,UDP不建立连接,也不保证数据的顺序和可靠性。每个数据报被独立发送,可能到达也可能丢失,但它的低开销使得它在实时应用中,如音频和视频流媒体,以及某些网络控制...
Tcp服务端与客户端的JAVA实例源代码 2个目标文件 摘要:Java源码,文件操作,TCP,服务器 Tcp服务端与客户端的JAVA实例源代码,一个简单的Java TCP服务器端程序,别外还有一个客户端的程序,两者互相配合可以开发出超多...
2.3.2 文件传输协议 14 2.3.3 Telnet 14 2.3.4 Email 14 2.3.5 WWW 14 2.3.6 USENET News 15 2.4 Intranet和Extranet概览 15 2.4.1 Intranet 15 2.4.2 将Intranet对外开放 16 2.5 Internet的明天 16 2.5.1 下一代...
二、TCP与UDP协议 TCP(Transmission Control Protocol)是一种面向连接的、可靠的传输协议,它保证了数据包的顺序到达和错误检测。而UDP(User Datagram Protocol)则是无连接的,速度快但不保证数据的可靠传输。...
24.4.3 混合TCP/IP安装 268 24.5 IP迁移辅助工具 268 24.5.1 NDS 268 24.5.2 DNS 269 24.5.3 DHCP 269 24.5.4 DDNS 269 24.5.5 SLP 269 24.5.6 兼容模式 269 24.5.7 迁移代理 270 24.6 迁移策略 270 24.6.1 使用测试...
包括开放式通信模型、TCP/IP通信模型、IP网络中的命名和寻址机制、地址解析及反向地址解析协议、DNS域字服务器、WINS、地址发现协议、IPv6、IP网络中的路由协议(RIP、OSPF等)、互联网打印协议、LDAP目录服务、远程...
Java项目通常会采用TCP或UDP作为传输层协议,因为它们能够保证数据的可靠传输。在此项目中,开发者可能利用了Java的Socket编程接口来建立客户端和服务端的连接,通过发送和接收字节流进行数据交换。TCP协议提供了一...
在Android平台上进行音频实时传输与播放涉及多个技术层面,包括音频采集、编码、网络传输、解码以及播放等。以下是对这些关键知识点的详细说明: 1. **音频采集**: 在Android设备上,我们可以使用`MediaRecorder`...
在Java中,这可以通过Socket编程实现,包括TCP和UDP协议。TCP提供面向连接的、可靠的通信,而UDP则是无连接的、不可靠的数据传输。Java的ServerSocket和Socket类提供了基础的网络通信接口。 2. **Java Web技术**:...
包括应用层组成的三种模式、C/S模式和P2P模式的要点、混合式P2P模式的要点、应用层常用协议的功能、Java TCP socket和UDP socket通信编程的要点、HTTP协议的性能优势、HTTP协议数据单元的数据结构、无状态协议与有...
在 Socket 通信中,可以使用 getInetAddress() 方法获取主机和客户机的 IP 地址,通过 Socket 实现基于 TCP 的通信需要创建 Socket 对象并与服务器建立连接,传输中文字符需要确保字符编码一致,通常设置为 UTF-8。...
2.3.2 文件传输协议 14 2.3.3 Telnet 14 2.3.4 Email 14 2.3.5 WWW 14 2.3.6 USENET News 15 2.4 Intranet和Extranet概览 15 2.4.1 Intranet 15 2.4.2 将Intranet对外开放 16 2.5 Internet的明天 16 2.5.1 下一代...
包括开放式通信模型、TCP/IP通信模型、IP网络中的命名和寻址机制、地址解析及反向地址解析协议、DNS域字服务器、WINS、地址发现协议、IPv6、IP网络中的路由协议(RIP、OSPF等)、互联网打印协议、LDAP目录服务、远程...
8. **网络编程**:对于网络游戏,JAVA的Socket编程是基础,用于客户端与服务器之间的数据传输。理解TCP和UDP协议,以及如何处理网络延迟和丢包问题是网络编程的关键。 9. **数据存储**:持久化数据,如用户进度、...
2. **局域网通信**:软件基于局域网进行文件传输,可能利用了TCP/IP协议栈中的UDP或者TCP协议进行数据传输,同时可能使用了多线程或多进程技术以提高传输速度和并发能力。 3. **图形用户界面(GUI)**:提供用户...