- 浏览: 44931 次
- 性别:
java建立UDP连接和建立TCP/IP连接一样简单,只用到了SocketAddress(绑定主机的IP地址和应用程序端口,包括自己的和发送地)、DatagramSocket(数据套接字,接收和发送数据包都靠它,同时在new该对象时需要try…catch,而SocketAddress则无需)、DatagramPacket(数据包对象,UDP数据都是一个包一个包发送的)这三个类。然后实现起来是非常简单的。首先是发送方new两个SocketAddress对象,一个参数写自己的机子,另一个写要发送的目标主机。然后把自己的SocketAddress对象传入DatagramSocket创建其对象,假设对象名为ds。再将要发送的数据连同目标主机的SocketAddress对象一起传入DatagramPacket创建其对象,设为dp。最后调用方法ds.send(dp);就OK了。这是发送方的,接收方差不多,实现起来没多大难度。不过众所周知,UDP有一个特点却是比不上TCP/IP的,那就是建立的连接不一定非常可靠,经常会出现丢包的情况,所以需要在发送过程中添加检测机制,而这也就大大加大了实现的难度。基本检测机制是:
发送方发送一个数据包,接收方接收后,发回一个应答包告诉发送方已收到消息,此应答包包含发送的消息的唯一序列号。关于这个序列号的唯一性设置我还不是很明白,所以在测试中就把第n条消息的n作为序列号了。若发送方在一定时间内(时间长短可自行设置)未收到应答包则重发消息。重发消息有两个原因:①接收方未收到,此时重发是应该的。②接收方收到消息但是发回的应答包丢失了,此时重发消息则重复了,所以在接收方还得添加一个机制:若收到的消息与以前发过的消息重复,则再次发送应答包。在这些机制下,能够初步的保证UDP传输的完整性。以下是实现代码:
发送端:
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.util.ArrayList; import java.util.List; public class UDPServer { public UDPServer() { try { sa = new InetSocketAddress("127.0.0.1", 9999); ds = new DatagramSocket(sa); saa = new InetSocketAddress("127.0.0.1", 1234); String msg = ""; startThread(); new Thread() { public void run() { while (true) { recMsg(); } } }.start(); for (int i = 1;; i++) { msg = "第" + i + "条消息"; Msg m = new Msg(msg, i); sendMsg(m); list.add(m); Thread.sleep(1000); } } catch (Exception e) { } } public void sendMsg(Msg m) { DatagramPacket dp; try { dp = new DatagramPacket(m.getmsg().getBytes(), m.getmsg() .getBytes().length, saa); ds.send(dp); m.setsendtime(System.currentTimeMillis()); } catch (IOException e) { e.printStackTrace(); } } public void recMsg() { byte[] buffer = new byte[20]; DatagramPacket dpp = new DatagramPacket(buffer, buffer.length); try { ds.receive(dpp); } catch (IOException e) { e.printStackTrace(); } String rec = new String(dpp.getData()).trim(); int id = Integer.parseInt(rec.substring(4, rec.length() - 3)); for (int i = 0; i < list.size(); i++) { if (id == list.get(i).getid()) { System.out.println("确认对方已收到第" + list.get(i).getid() + "条消息,从队列中除去"); list.remove(i); } } } public void startThread() { new Thread() { public void run() { while (true) { // 如果list里面有元素 if (list.size() > 1) { for (int i = 0; i < list.size(); i++) { if (System.currentTimeMillis() - list.get(i).getsendtime() > 3000 && list.get(i).gettime() < 4) { sendMsg(list.get(i)); System.out.println("重发第" + list.get(i).getid() + "条消息第" + list.get(i).gettime() + "次"); if (list.get(i).gettime() == 3) { System.out.println("重发第" + list.get(i).getid() + "条消息已超过4次,丢弃包");// System.exit(0); list.remove(i); } else { list.get(i).settime( list.get(i).gettime() + 1); } } } } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); } public static void main(String[] args) { new UDPServer(); } class Msg { public Msg(String msg, int id) { this.msg = msg; this.id = id; } public void setid(int i) { id = i; } public int getid() { return id; } public void setmsg(String newmsg) { msg = newmsg; } public String getmsg() { return msg; } public void settime(int i) { time = i; } public int gettime() { return time; } public void setsendtime(long time) { lastsendtime = time; } public long getsendtime() { return lastsendtime; } private int id; private String msg; private int time; private long lastsendtime; } List<Msg> list = new ArrayList<Msg>(); SocketAddress sa; DatagramSocket ds; SocketAddress saa; }
接收端:
import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Font; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.util.ArrayList; import java.util.List; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.UIManager; public class UDPClient { JFrame f; JTextArea jta, jta2; SocketAddress sa; SocketAddress saa; DatagramSocket ds; List<Msg> list = new ArrayList<Msg>(); public UDPClient() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception e) { } Font font = new Font("Dialog", Font.PLAIN, 12); f = new JFrame(); jta = new JTextArea(); jta.setFont(font); jta2 = new JTextArea(); jta2.setFont(font); JScrollPane jsp = new JScrollPane(jta); JScrollPane jsp2 = new JScrollPane(jta2); jsp.setPreferredSize(new Dimension(500, 400)); jsp2.setPreferredSize(new Dimension(300, 400)); f.setLayout(new FlowLayout()); f.add(jsp); f.add(jsp2); f.pack(); f.setLocationRelativeTo(null); f.setDefaultCloseOperation(3); f.setVisible(true); sa = new InetSocketAddress("127.0.0.1", 1234); saa = new InetSocketAddress("127.0.0.1", 9999); new Thread() { public void run() { recMsg(); } }.start(); startThread(); } public void recMsg() { try { ds = new DatagramSocket(sa); while (true) { byte[] buffer = new byte[20]; DatagramPacket dpp = new DatagramPacket(buffer, buffer.length); jta.append("等待数据...\n"); ds.receive(dpp); String rec = new String(dpp.getData()).trim(); if (check(rec)) { jta.append(rec + "\n"); int id = Integer .parseInt(rec.substring(1, rec.length() - 3)); Msg m = new Msg(rec, id); list.add(m); send(m); } } } catch (IOException e) { e.printStackTrace(); } } public boolean check(String msg) { if (list.size() > 0) { for (int i = 0; i < list.size(); i++) { if (list.get(i).getmsg().equals("msg")) { send(list.get(i)); return false; } } } return true; } public void send(Msg m) { String msg = "已收到第" + m.getid() + "条消息"; try { DatagramPacket dp = new DatagramPacket(msg.getBytes(), msg.getBytes().length, saa); ds.send(dp); jta2.append(msg + "\n"); m.setrectime(System.currentTimeMillis()); } catch (IOException e) { e.printStackTrace(); } } public void startThread() { new Thread() { public void run() { while (true) { if (list.size() > 0) { for (int i = 0; i < list.size(); i++) { if (System.currentTimeMillis() - list.get(i).getrectime() > 5000) { list.remove(i); jta2.append("确认已收到第" + list.get(i).getid() + "条消息,从队列中除去\n"); } } } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); } public static void main(String[] args) { new UDPClient(); } class Msg { public Msg(String msg, int id) { this.msg = msg; this.id = id; } public void setid(int i) { id = i; } public int getid() { return id; } public void setmsg(String newmsg) { msg = newmsg; } public String getmsg() { return msg; } public void settime(int i) { time = i; } public int gettime() { return time; } public void setrectime(long time) { lastrectime = time; } public long getrectime() { return lastrectime; } private int id; private String msg; private int time; private long lastrectime; } }
运行结果如图所示:
发表评论
-
PlaySound和sndPlaySound的三种播放音乐方法
2012-11-16 21:18 8243首先要添加头文件 #include "mmsyst ... -
PlaySound和sndPlaySound的三种播放音乐方法
2012-11-16 21:16 1首先要添加头文件 #incl ... -
android中的Dialog
2012-06-28 20:20 1544android手机和PC机一样,也会根据各种不同程 ... -
关于网络通信中如何传输对象的问题
2012-03-14 17:09 1758我们不管在用TC ... -
设计模式所感
2012-03-10 22:03 1109刚接触高级语言编程的人是不会考虑怎么去设计类之间的 ... -
Hash表的建立及增删改查相关操作
2012-03-04 21:41 16821、什么是hash? Hash,一般翻译做“散列”,也 ... -
c语言实现简单链表建立及筛选
2012-02-23 01:05 1663最近在重新复习c,其实也可以算是学习吧。由于大一时上课没怎么听 ... -
小小的心得
2011-12-12 11:51 979关于jsp的,因为最近要做数据库,所以看了看,不过估计到最后数 ... -
javah的classpath路径设置
2011-11-20 22:01 4887貌似javah的classpath路径必须要设置~~ ... -
JTree实现windows文件打开
2011-11-16 19:46 1457package cn.zyf.java树1116; im ... -
文件搜索的简单实现
2011-10-24 00:46 1312快一个月没写总结了, ... -
java关键字总结
2011-09-25 17:09 853首先我们得明确,java中 ... -
关于事件源的应用
2011-09-21 00:52 826今天被画图板的一个鼠标右键单击处理事件的事情搞得晕头转 ...
相关推荐
本文将深入探讨如何在UDP的基础上,通过添加验证和重发机制,实现稳定且高效的文件传输。 #### UDP协议特性与局限 UDP协议设计的初衷是为了提供一种轻量级、快速的通信方式,它不进行三次握手建立连接,也不进行...
总结来说,实现UDP上的可靠文件传输,关键在于设计合适的错误检测和恢复策略,如使用滑动窗口协议配合重传机制。通过这种方式,即使UDP本身的不可靠特性,也可以通过软件层面的手段来弥补,达到类似TCP的可靠传输...
可能的策略包括重发机制、错误检测码如CRC(Cyclic Redundancy Check)等。 5. **视频编码与解码**:视频数据通常是经过编码的,如H.264、VP9等,发送前需要将其编码为字节流。接收端收到字节流后,需解码恢复成...
实现一个基于UDP的文件传输系统需要考虑重发机制,因为UDP协议本身并不提供任何内置的重传功能。通过TNMUDP控件,我们可以创建一个简单的客户端-服务器模型,允许文件在两者之间可靠地传输。首先,我们需要在服务器...
3. **数据包重发机制** - 当发送端在规定时间内没有收到接收端的确认时,重新发送相应的数据包。 - 使用互斥锁来确保对缓冲队列的操作是线程安全的。 #### 六、总结 通过上述介绍,我们可以看出,虽然UDP自身不...
与TCP相比,UDP提供了较少的错误检测和流量控制机制,因此它更注重速度和效率,常用于实时应用如在线视频、语音通话以及简单的文件传输。 在这个“UDP简单文件传输”项目中,开发人员利用MFC(Microsoft Foundation...
总的来说,UDT通过在UDP基础上添加额外的机制,实现了高效且可靠的传输服务,是应对大数据传输挑战的一种有效解决方案。通过阅读"UDT2"的源代码,我们可以更深入地理解其实现细节,为自己的项目或研究提供参考。
为了确保数据的完整性,此组件实现了检测丢包并进行重发的功能。通常,这会通过序列号和超时重传策略来实现。 3. **简单易用的API**:描述中提到,该组件的调用方式简单,这意味着开发者可以快速集成到自己的应用中...
3. **错误检测与重传**:由于UDP的不可靠性,我们需要引入一种机制来检测丢失的数据包,并要求发送方重新发送。可以使用序列号和确认机制,当接收端接收到数据包后,发送确认信息,如果发送方在一定时间内未收到确认...
总的来说,C#中通过UDP实现可靠传输需要综合运用多种技术,包括序列号、确认机制、重传超时、滑动窗口、数据校验和流量控制。这些技术能够帮助我们在保留UDP优点的同时,克服其天生的不可靠性,实现类似TCP的传输...
1. 设置超时重发机制:如果在一定时间内未收到确认,客户端可以重发数据报。 2. 序列号:在协议头中加入序列号,便于检测乱序的数据报。 3. 滑动窗口:通过限制同时未确认的数据报数量,可以控制网络拥塞并提高效率...
在计算机网络中,序列号和TCP/UDP重发协议是确保数据可靠传输的关键机制。滑动窗口协议是一种流量控制策略,用于管理数据在网络中的发送速率,以防止数据包的丢失、重复或乱序。 滑动窗口协议的工作原理是基于两个...
### 基于UDP通信协议的设计与实现 #### 一、引言 随着信息技术的快速发展,网络通信成为了现代社会不可或缺的一部分。TCP/IP协议族作为互联网通信的基础,其成员之一的用户数据报协议(UDP)因其简单高效的特点,...
然而,在文件传输这种对数据完整性和顺序有较高要求的场景下,单纯使用UDP可能不够,我们需要自行实现一些机制来增强其可靠性。 在C#中,我们可以使用`System.Net.Sockets.UdpClient`类来操作UDP套接字。这个类提供...
2. **丢包重发机制**:由于UDP的不可靠性,我们需要自行实现丢包检测和重发策略。可以设置一个超时时间,如果在该时间内未收到接收方的确认信息(例如,通过TCP或另一条UDP通道返回一个确认消息),则重新发送数据包...
### 基于UDP通信协议的设计与实现 #### 一、引言 随着信息技术的快速发展,网络通信成为了现代社会不可或缺的一部分。TCP/IP协议族作为互联网通信的基础,在数据传输方面发挥着核心作用。其中,用户数据报协议...
【C语言UDP传输系统源码】是一个用于学习和参考的游戏源码项目,它涉及了网络编程中的基础概念,特别是用户数据报协议(UDP)的应用。UDP是互联网协议族中的一个无连接、不可靠的传输协议,它在实现时通常比TCP...
标题中的“基于udp的局域网聊天及文件传输程序”是指使用UDP(User Datagram Protocol)协议在局域网内实现的通信应用。UDP是一种无连接的、不可靠的传输层协议,它不保证数据包的顺序和完整性,但因为其简单高效的...
在这个场景中,我们关注的是使用C#实现UDP(用户数据报协议)的组包、分包、接收和发送功能,以及数据包的重发机制。 首先,UDP是一种无连接的传输层协议,它不保证数据的顺序和可靠性,但相比TCP,其速度更快,...
- **错误检测**:由于UDP的不可靠性,需要自定义错误检测机制,比如添加校验和。 - **数据包排序**:如果数据需要按顺序处理,服务器端可能需要维护一个队列来重新排序收到的数据包。 - **超时重发**:对于关键数据...