java.net包的DatagramSocket和DatagramPacket

来源:互联网 发布:java定义string数组 编辑:程序博客网 时间:2024/06/10 22:53

转自:http://blog.csdn.net/sinat_16596967/article/details/37960545


本博文主要简述TCP/UDP的比较和应用场景,以及java.net包下基于DatagramSocket/DatagramPacket的编程和源码分析

TCP与UDP
    作为传输层两个重要的协议,得到广泛的使用。
TCP
    1. 面向连接,速度较慢,证明:连接双方的一方主动断开连接之后,另一方的recieve()会立即作出响应。
    2. 面向字节流,虽然应用程序和TCP的交互是一次一个数据块(大小不等),但TCP把应用程序看成是一连串的无结构的字节。流。TCP有一个缓冲,当应用程序传送的数据块太长,TCP就可以把它划分短一些再传送。如果应用程序一次只发送一个字节,TCP也可以等待积累有足够多的字节后再构成报文段发送出去。
    3. 通信方式:全双工通信(发送缓存&接收缓存)。
    4. 保证数据正确性。
    5. 具备流量控制和拥塞控制。
    6. 应用场景:浏览器surfing(Http)、文件传输(FTP)、接发邮件(SMTP,POP)、远程登录(telnet、ssh)。
UDP
    1. 面向非连接,速度较快,证明:连接双方的一方主动断开连接之后,另一方的recieve()仍然阻塞。
    2. 面向数据包,UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界。这也就是说,应用层交给UDP多长的报文,UDP就照样发送,即一次发送一个报文。
    3. 通信方式:一对一、一对多、多对一、多对多。
    4. 可能丢包,譬如我们看视频时失帧就是丢包的结果。
    5. 无流量控制和拥塞控制。
    6. 应用场景:即时聊天(QQ)、视频流(Youku的视频)、语音流(YY语音)等,适用于多播和广播的应用场景。

DatagramSocket/DatagramPacket
    有人把DatagramSocket比作码头,把DatagramPacket比作集装箱,前者只是存放各种数据包的地方,而后者决定数据包的内容和目的地址。这种比喻很是恰当,这也意味着server端和client端更为简单也更为相似。
    下面这段代码Server开启端口为4444的服务,接收数据并返回ok。而Client发送数据并打印server的回执。

//Server
importjava.io.IOException;
importjava.net.DatagramPacket;
importjava.net.DatagramSocket;
public class DataAccepterServer {
       public static void main(String[] args) throwsIOException {
              byte[] inBuff = newbyte[4096]; // 设置接收的buffer
              DatagramPacket inPacket = newDatagramPacket(inBuff, inBuff.length);// 设置接收的packet
              DatagramPacketoutPacket;
              DatagramSocket socket = newDatagramSocket(4444);// 创建端口为4444的UDP服务
              //socket.setSoTimeout(1000);//设置socket.receive的timeout
              boolean flag = true;
              while (flag) {// 服务一直开启
                    socket.receive(inPacket);// 阻塞方法,为设置sotimeout时一直等待
                     if (inBuff== inPacket.getData()) { // 判断是否正确接收到packet
                    System.out.println(newString(inBuff, 0, inBuff.length));// 打印client发来的消息
                    outPacket = newDatagramPacket("OK".getBytes(), "OK".length(),
                                 inPacket.getAddress(),inPacket.getPort());// 设置发送的packet
                           socket.send(outPacket);// 发送消息到client
                     } else{
                           System.out.println("get packet wrong!");
                     }
              }
       }
}
    DatagramSocket与DatagramPacket包揽了全部的工作:
    第一步:设置接收的byte[]数组,和对应的DatagramPacket,接收的数据放入byte[],如果过长则截断。
    第二部:DatagramSocket socket = newDatagramSocket(4444);创建服务。
    1. 创建DatagramSocketImpl对象如PlainDatagramSocketImpl。使用PlainDatagramSocketImpl的native方法datagramSocketCreate(),进行服务的创建。接着进行绑定操作,使用PlainDatagramSocketImpl的native方法bind0(intlport, InetAddress laddr),进行服务的绑定。
    2. socket.receive(inPacket);把接收到的数据传入inPacket中,也可以从byte[]里面得到。recieve方法在每次接收数据前服务进行检测(由安全机制SecurityManager完成),再使用PlainDatagramSocketImpl的native方法receive0(DatagramPacketp),进行数据的接受,如果没有设置timeout,会一直阻塞。
    3. 接收到数据后,打印,并构造DatagramSocket,该DatagramSocket拥有内容、长度、目的地址和服务端口。
    4. 发送回执DatagramSocket对象,该方法同样进行检测(由安全机制SecurityManager完成),再使用PlainDatagramSocketImpl的native方法send(),进行数据的发送。
    5. 循环2、3、4。

//Client
import java.io.IOException;
importjava.net.DatagramPacket;
importjava.net.DatagramSocket;
importjava.net.InetAddress;
    
public class DataSender{
        public static void main(String[] args) throwsIOException,
                                        InterruptedException{
               byte[] inBuff = new byte[4096];//设置接收的buffer
               DatagramPacket inPacket = newDatagramPacket(inBuff, inBuff.length);// 设置接收的packet
               byte[] outBuff = "Hello Server! This is clenta!".getBytes();// 设置发送buffer
               DatagramSocket socket = new DatagramSocket();//默认随机端口发送udp包
               socket.setSoTimeout(3000);//设置接收回执timeout
               //socket.connect(InetAddress.getByName("127.0.0.1"),4444);
               DatagramPacket outPacket = newDatagramPacket(new byte[0], 0,
               InetAddress.getByName("127.0.0.1"), 4444);//设置发送packet
               for (int i = 0; i < 5; i++) {//发送五次信息
                        outPacket.setData(outBuff);
                        socket.send(outPacket);//发送消息到server
                        socket.receive(inPacket);//接收server的回执,直到timeout
                        System.out.println(newString(inBuff, 0, inBuff.length));// 打印回执
                        Thread.sleep(1000);
               }
               socket.close();
       }       
    DatagramSocket与DatagramPacket包揽了全部的功能,方法与Server端基本一致。
    注意的地方有:
    1. socket.setSoTimeout(3000);如果3秒终内服务端未回执,会继续往下执行。
    2. socket.connect(InetAddress.getByName("127.0.0.1"),4444);如果设置该想,这是一个专用链接,发送的DatagramPacket的目的地址和服务端口也必须一直,否则报错。

阅读全文
0 0
原创粉丝点击