ImageVerifierCode 换一换
格式:DOCX , 页数:11 ,大小:21.61KB ,
资源ID:7509284      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/7509284.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(使用DatagramSocket发送接收数据Socket之UDP套接字.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

使用DatagramSocket发送接收数据Socket之UDP套接字.docx

1、使用DatagramSocket发送接收数据Socket之UDP套接字使用DatagramSocket发送、接收数据(Socket之UDP套接字)来源:17.4.2 使用DatagramSocket发送、接收数据(1)Java使用DatagramSocket代表UDP协议的Socket,DatagramSocket本身只是码头,不维护状态,不能产生IO流,它的唯一作用就是接收和发送数据报,Java使用DatagramPacket来代表数据报,DatagramSocket接收和发送的数据都是通过DatagramPacket对象完成的。先看一下DatagramSocket的构造器。Datagram

2、Socket():创建一个DatagramSocket实例,并将该对象绑定到本机默认IP地址、本机所有可用端口中随机选择的某个端口。DatagramSocket(int prot):创建一个DatagramSocket实例,并将该对象绑定到本机默认IP地址、指定端口。DatagramSocket(int port, InetAddress laddr):创建一个DatagramSocket实例,并将该对象绑定到指定IP地址、指定端口。通过上面三个构造器中的任意一个构造器即可创建一个DatagramSocket实例,通常在创建服务器时,创建指定端口的DatagramSocket实例-这样保证其他

3、客户端可以将数据发送到该服务器。一旦得到了DatagramSocket实例之后,就可以通过如下两个方法来接收和发送数据。receive(DatagramPacket p):从该DatagramSocket中接收数据报。send(DatagramPacket p):以该DatagramSocket对象向外发送数据报。从上面两个方法可以看出,使用DatagramSocket发送数据报时,DatagramSocket并不知道将该数据报发送到哪里,而是由DatagramPacket自身决定数据报的目的地。就像码头并不知道每个集装箱的目的地,码头只是将这些集装箱发送出去,而集装箱本身包含了该集装箱的目的

4、地。下面看一下DatagramPacket的构造器。DatagramPacket(byte buf,int length):以一个空数组来创建DatagramPacket对象,该对象的作用是接收DatagramSocket中的数据。DatagramPacket(byte buf, int length, InetAddress addr, int port):以一个包含数据的数组来创建DatagramPacket对象,创建该DatagramPacket对象时还指定了IP地址和端口-这就决定了该数据报的目的地。DatagramPacket(byte buf, int offset, int le

5、ngth):以一个空数组来创建DatagramPacket对象,并指定接收到的数据放入buf数组中时从offset开始,最多放length个字节。DatagramPacket(byte buf, int offset, int length, InetAddress address, int port):创建一个用于发送的DatagramPacket对象,指定发送buf数组中从offset开始,总共length个字节。当Client/Server程序使用UDP协议时,实际上并没有明显的服务器端和客户端,因为两方都需要先建立一个DatagramSocket对象,用来接收或发送数据报,然后使用Da

6、tagramPacket对象作为传输数据的载体。通常固定IP地址、固定端口的DatagramSocket对象所在的程序被称为服务器,因为该DatagramSocket可以主动接收客户端数据。在接收数据之前,应该采用上面的第一个或第三个构造器生成一个DatagramPacket对象,给出接收数据的字节数组及其长度。然后调用DatagramSocket 的receive()方法等待数据报的到来,receive()将一直等待(该方法会阻塞调用该方法的线程),直到收到一个数据报为止。如下代码所示:1. / 创建一个接收数据的DatagramPacket对象 2. DatagramPacket pack

7、et=new DatagramPacket(buf, 256); 3. / 接收数据报 4. socket.receive(packet); 在发送数据之前,调用第二个或第四个构造器创建DatagramPacket对象,此时的字节数组里存放了想发送的数据。除此之外,还要给出完整的目的地址,包括IP地址和端口号。发送数据是通过DatagramSocket的send()方法实现的,send()方法根据数据报的目的地址来寻径以传送数据报。如下代码所示:1. / 创建一个发送数据的DatagramPacket对象 2. DatagramPacket packet = new DatagramPacke

8、t(buf, length, address, port); 3. / 发送数据报 4. socket.send(packet); 使用DatagramPacket接收数据时,会感觉DatagramPacket设计得过于烦琐。开发者只关心该DatagramPacket能放多少数据,而DatagramPacket是否采用字节数组来存储数据完全不想关心。但Java要求创建接收数据用的DatagramPacket时,必须传入一个空的字节数组,该数组的长度决定了该DatagramPacket能放多少数据,这实际上暴露了DatagramPacket的实现细节。接着DatagramPacket又提供了一个

9、getData()方法,该方法又可以返回Datagram Packet对象里封装的字节数组,该方法更显得有些多余-如果程序需要获取DatagramPacket里封装的字节数组,直接访问传给 DatagramPacket构造器的字节数组实参即可,无须调用该方法。当服务器端(也可以是客户端)接收到一个DatagramPacket对象后,如果想向该数据报的发送者反馈一些信息,但由于UDP协议是面向非连接的,所以接收者并不知道每个数据报由谁发送过来,但程序可以调用DatagramPacket的如下3个方法来获取发送者的IP地址和端口。InetAddress getAddress():当程序准备发送此数

10、据报时,该方法返回此数据报的目标机器的IP地址;当程序刚接收到一个数据报时,该方法返回该数据报的发送主机的IP地址。int getPort():当程序准备发送此数据报时,该方法返回此数据报的目标机器的端口;当程序刚接收到一个数据报时,该方法返回该数据报的发送主机的端口。SocketAddress getSocketAddress():当程序准备发送此数据报时,该方法返回此数据报的目标SocketAddress;当程序刚接收到一个数据报时,该方法返回该数据报的发送主机的SocketAddress。getSocketAddress()方法的返回值是一个SocketAddress对象,该对象实际上就

11、是一个IP地址和一个端口号。也就是说,SocketAddress对象封装了一个InetAddress对象和一个代表端口的整数,所以使用SocketAddress对象可以同时代表IP地址和端口。17.4.2 使用DatagramSocket发送、接收数据(2)下面程序使用DatagramSocket实现了Server/Client结构的网络通信。本程序的服务器端使用循环1000次来读取DatagramSocket中的数据报,每当读取到内容之后便向该数据报的发送者送回一条信息。服务器端程序代码如下。程序清单:codes1717.4UdpServer.java1. public class UdpS

12、erver 2. 3. public static final int PORT = 30000; 4. / 定义每个数据报的最大大小为4KB 5. private static final int DATA_LEN = 4096; 6. / 定义接收网络数据的字节数组 7. byte inBuff = new byteDATA_LEN; 8. / 以指定字节数组创建准备接收数据的DatagramPacket对象 9. private DatagramPacket inPacket = 10. new DatagramPacket(inBuff , inBuff.length); 11. /

13、定义一个用于发送的DatagramPacket对象 12. private DatagramPacket outPacket; 13. / 定义一个字符串数组,服务器端发送该数组的元素 14. String books = new String 15. 16. 疯狂Java讲义, 17. 轻量级Java EE企业应用实战, 18. 疯狂Android讲义, 19. 疯狂Ajax讲义 20. ; 21. public void init()throws IOException 22. 23. try( 24. / 创建DatagramSocket对象 25. DatagramSocket soc

14、ket = new DatagramSocket(PORT) 26. 27. / 采用循环接收数据 28. for (int i = 0; i 1000 ; i+ ) 29. 30. / 读取Socket中的数据,读到的数据放入inPacket封装的数组里 31. socket.receive(inPacket); 32. / 判断inPacket.getData()和inBuff是否是同一个数组 33. System.out.println(inBuff = inPacket.getData(); 34. / 将接收到的内容转换成字符串后输出 35. System.out.println(n

15、ew String(inBuff, 0 , inPacket.getLength(); 36. / 从字符串数组中取出一个元素作为发送数据 37. byte sendData = booksi % 4.getBytes(); 38. / 以指定的字节数组作为发送数据,以刚接收到的DatagramPacket的 39. / 源SocketAddress作为目标SocketAddress创建DatagramPacket 40. outPacket = new DatagramPacket(sendData 41. , sendData.length , inPacket.getSocketAddr

16、ess(); 42. / 发送数据 43. socket.send(outPacket); 44. 45. 46. 47. public static void main(String args) 48. throws IOException 49. 50. new UdpServer().init(); 51. 52. 上面程序中的粗体字代码就是使用DatagramSocket发送、接收DatagramPacket的关键代码,该程序可以接收1000个客户端发送过来的数据。客户端程序代码也与此类似,客户端采用循环不断地读取用户键盘输入,每当读取到用户输入的内容后就将该内容封装成Datagram

17、Packet数据报,再将该数据报发送出去;接着把DatagramSocket中的数据读入接收用的DatagramPacket中(实际上是读入该DatagramPacket所封装的字节数组中)。客户端程序代码如下。17.4.2 使用DatagramSocket发送、接收数据(3)程序清单:codes1717.4UdpClient.java1. public class UdpClient 2. 3. / 定义发送数据报的目的地 4. public static final int DEST_PORT = 30000; 5. public static final String DEST_IP =

18、 127.0.0.1; 6. / 定义每个数据报的最大大小为4KB 7. private static final int DATA_LEN = 4096; 8. / 定义接收网络数据的字节数组 9. byte inBuff = new byteDATA_LEN; 10. / 以指定的字节数组创建准备接收数据的DatagramPacket对象 11. private DatagramPacket inPacket = 12. new DatagramPacket(inBuff , inBuff.length); 13. / 定义一个用于发送的DatagramPacket对象 14. priva

19、te DatagramPacket outPacket = null; 15. public void init()throws IOException 16. 17. try( 18. / 创建一个客户端DatagramSocket,使用随机端口 19. DatagramSocket socket = new DatagramSocket() 20. 21. / 初始化发送用的DatagramSocket,它包含一个长度为0的字节数组 22. outPacket = new DatagramPacket(new byte0 , 0 , InetAddress.getByName(DEST_I

20、P) , DEST_PORT); 23. / 创建键盘输入流 24. Scanner scan = new Scanner(System.in); 25. / 不断地读取键盘输入 26. while(scan.hasNextLine() 27. 28. / 将键盘输入的一行字符串转换成字节数组 29. byte buff = scan.nextLine().getBytes(); 30. / 设置发送用的DatagramPacket中的字节数据 31. outPacket.setData(buff); 32. / 发送数据报 33. socket.send(outPacket); 34. /

21、读取Socket中的数据,读到的数据放在inPacket所封装的字节数组中 35. socket.receive(inPacket); 36. System.out.println(new String(inBuff , 0 , inPacket.getLength(); 37. 38. 39. 40. public static void main(String args) 41. throws IOException 42. 43. new UdpClient().init(); 44. 45. 上面程序中的粗体字代码同样也是使用DatagramSocket发送、接收DatagramPac

22、ket的关键代码,这些代码与服务器端代码基本相似。而客户端与服务器端的唯一区别在于:服务器端的IP地址、端口是固定的,所以客户端可以直接将该数据报发送给服务器端,而服务器端则需要根据接收到的数据报来决定反馈数据报的目的地。读者可能会发现,使用DatagramSocket进行网络通信时,服务器端无须也无法保存每个客户端的状态,客户端把数据报发送到服务器端后,完全有可能立即退出。但不管客户端是否退出,服务器端都无法知道客户端的状态。当使用UDP协议时,如果想让一个客户端发送的聊天信息被转发到其他所有的客户端则比较困难,可以考虑在服务器端使用Set集合来保存所有的客户端信息,每当接收到一个客户端的数

23、据报之后,程序检查该数据报的源SocketAddress是否在Set集合中,如果不在就将该SocketAddress添加到该Set集合中。这样又涉及一个问题:可能有些客户端发送一个数据报之后永久性地退出了程序,但服务器端还将该客户端的SocketAddress保存在Set集合中总之,这种方式需要处理的问题比较多,编程比较烦琐。幸好Java为UDP协议提供了MulticastSocket类,通过该类可以轻松地实现多点广播。Socket之UDP套接字UDP套接字:UDP套接字的使用是通过DatagramPacket类和DatagramSocket类,客户端和服务器端都是用DatagramPacke

24、t类来接收数据,使用DatagramSocket类来发送数据。UDP客户端:也是主要执行三个步骤。1.创建DatagramSocket实例;2.使用DatagramSocket类的send()和receive()方法发送和接收DatagramPacket实例;3.最后使用DatagramSocket类的close()方法销毁该套接字。下面是例子,它主要执行三个步骤,1.向服务器发送信息;2.在receive()方法上最多阻塞等待3秒钟,在超时前若没有收到响应,则重发请求(最多重发5次);3.关闭客户端。javaview plaincopy1. /UDPEchoClientTimeout.jav

25、a2. 3. import.DatagramSocket;4. import.DatagramPacket;5. import.InetAddress;6. importjava.io.IOException;7. importjava.io.InterruptedIOException;8. 9. publicclassUDPEchoClientTimeout10. 11. privatestaticfinalintTIMEOUT=3000;/设置超时为3秒12. privatestaticfinalintMAXTRIES=5;/最大重发次数5次13. 14. publicstaticvoi

26、dmain(Stringargs)throwsIOException15. 16. if(args.length3)/Testforcorrect#ofargs17. thrownewIllegalArgumentException(Parameter(s):);18. 19. InetAddressserverAddress=InetAddress.getByName(args0);/服务器地址20. /ConverttheargumentStringtobytesusingthedefaultencoding21. /发送的信息22. bytebytesToSend=args1.getBy

27、tes();23. 24. intservPort=(args.length=3)?Integer.parseInt(args2):7;25. 26. DatagramSocketsocket=newDatagramSocket();27. 28. socket.setSoTimeout(TIMEOUT);/设置阻塞时间29. 30. DatagramPacketsendPacket=newDatagramPacket(bytesToSend,/相当于将发送的信息打包31. bytesToSend.length,serverAddress,servPort);32. 33. DatagramP

28、acketreceivePacket=/相当于空的接收包34. newDatagramPacket(newbytebytesToSend.length,bytesToSend.length);35. 36. inttries=0;/Packetsmaybelost,sowehavetokeeptrying37. booleanreceivedResponse=false;38. do39. socket.send(sendPacket);/发送信息40. try41. socket.receive(receivePacket);/接收信息42. 43. if(!receivePacket.getAddress().equals(serverAddress)/Checksource44. thrownewIOException(Receivedpacketfromanunknownsource);45. 46. receivedResponse=true;47. catch(InterruptedIOExceptione)/当receive不到信息或者receive时

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1