互联网程序设计第六讲

第6讲 UDP套接字程序设计

完成日期:2018.10.31
GitHub:https://github.com/fyinh/network_programming_course/tree/master/ch06


教学与实践目的:学会使用UDP套接字来实现网络应用程序设计。

UDP通信特点:
(1) UDP有别于TCP,有自己独立的套接字(IP+PORT),它们的端口号不冲突;
(2) UDP 通信前通常[不]需要连接;
(3) 基于用户数据报文(包)读写;
(4) UDP通信一般用于线路质量好的环境,如局域网内。
几个关键的Java类:DatagramSocket,DatagramPacket,MulticastSocket。

1. 程序设计第一步:创建UDPClient.java程序

  UDPClient.java源程序见附录1。
(1)UDP套接字类: DatagramSocket
  不像TCP通信有客户套接字Socket和服务器套接字ServerSocket两种,而UDP套接字只有一种DatagramSocket,不区分客户套接字和服务器套接字。
UDP套接字的两个重要方法是:
  发送网络数据用:

DatagramSocket.send(packet); //发送一个数据包

  接收网络数据用:

DatagramSocket.receiver(packet);//接收一个数据包`

  其中packet属于 DatagramPacket报文类的一个实例对象,用户数据封装在packet中。

(2)UDP数据报文类:DatagramPacket。
  TCP发送数据是基于字节流的,而UDP发送数据是基于报文DatagramPacket,网络中传递的UDP数据都要封装在报文中。
报文类的两个重要方法是:

Byte[] b=DatagramPacket.getData();//从报文中取数据
DatagramPacket.setData(String msg);//往报文中填充数据

2. 程序设计第二步:创建UDPClientJFrame.java程序

  用户界面如下图所示。
互联网程序设计第六讲_第1张图片
演示过程:
(1)在“连接”按钮中实例化UDPClient对象,并启动接收信息的“读线程”;
(2)在“发送”按钮中设置发送信息的动作代码;
(3)在“退出”按钮中设置退出程序运行代码。
(4)验证和服务器通话。

3. 程序设计第三步:创建UDPServer.java程序

  根据UDPClient.java程序,创建对应的UDPServer服务器程序。服务器程序的功能是接收用户信息,并能自动返回用户信息。

4. 程序设计进阶之一:组播程序设计(源程序见附录2)

  组播是指在一群用户范围内发送和接收信息,该信息具有共享性。UDP具有组播功能,而TCP不具有。
  组播地址的格式为:224...*,比如:224.1.10.10。组播地址号唯一标示一群用户(一定网络范围内,仅限于局域网络内或有些自治系统内支持组播)。

组播套接字类:MulticastSocket及其几个重要的方法:
(1)路由器、交换机一般只转发和终端机一致IP地址和广播地址数据,终端机如何知道要接收组内信息?要先声明加入或退出某一组播组,其方法是:

MulticastSocket  ms=new MulticastSocket(8900);
ms.joinGroup(groupIP);//加入groupIP组
//作用:告知自己的网络层该IP地址的包要收;
//转告上联的路由器这样的IP地址包要转发。
ms.leaveGroup(groupIP);//退出groupIP组

(2)组内接收和发送信息的方法同UDP单播,其方法是:
ms.send(packet);
ms.receiver(packet).
(3)独立完成组播程序MulticastQQ.java和MulticastQQJFrame.java,组播套接字为:[224.0.1.8:8900],在组内发言要求以“201********* 姓名*”为信息头。其效果如下图所示,要求每位同学都能看到组内其他同学的留言。
互联网程序设计第六讲_第2张图片

5.程序设计进阶之二:基于UDP技术实现一个通用聊天软件

  要求支持用户验证、在线提示、单人及群组聊天等。

附录:
一、 UDP客户端程序

public class UDPClient {
    private int remotePort;
    private InetAddress  remoteIP;
    private DatagramSocket socket; //UDP套接字 
    
    public UDPClient(String ip, String port) throws IOException{
        this.remotePort=Integer.parseInt(port);
        this.remoteIP=InetAddress.getByName(ip);
     
        //创建一个UDP套接字,与本地任意一个未使用的UDP端口绑定
        socket=new DatagramSocket(); 
        //与本地一个固定的UDP端口绑定
        //socket=new DatagramSocket(9000);
    }
    
    //定义一个数据的发送方法。
    public void send(String msg){
        try {
            byte[] outputData = msg.getBytes("GB2312");
            //构建一个数据报文。
            DatagramPacket outputPacket;
            outputPacket = new DatagramPacket(outputData,outputData.length,remoteIP,remotePort);
            socket.send(outputPacket); //给UDPServer发送数据报
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
        
    //定义一个数据的接收方法。
    public String receive(){//throws IOException{
        String msg;
        //先准备一个空数据报文
        DatagramPacket inputPacket = new DatagramPacket(new byte[512],512);
        try{
            //阻塞语句,有数据就装包,以装完或装满为此.
            socket.receive(inputPacket);
            //从报文中取出字节数据并装饰成字符。
            msg = new String(inputPacket.getData(),0,inputPacket.getLength(),"GB2312");
        }catch(IOException ex){
            msg = null;
        }
        return msg;
    }
    
    public void close(){
        if(socket != null){
            socket.close();//释放本地接口
        }
    }   
}

二、组播程序

public class MulticastQQ {
    InetAddress groupIP;// = InetAddress.getByName("224.0.1.8");
    int port = 8900;
    MulticastSocket ms = null; //组播套接字
    
    byte[] inBuff;
    byte[] outBuff;
    
    public MulticastQQ() throws IOException
    {
        groupIP = InetAddress.getByName("224.0.1.8");
        
        ms = new MulticastSocket(port); //开启一个组播端口(UDP端口)
        ms.joinGroup(groupIP); //告诉网卡这样的IP地址数据包要接收
        
        inBuff = new byte[1024];
        outBuff = new byte[1024];
    }
    
    public void send(String msg)
    {
        try
        {
            outBuff = ("20121000000老师 : " + msg).getBytes("GBK");
            DatagramPacket outdp = new DatagramPacket(outBuff, outBuff.length, groupIP, port);
            ms.send(outdp);
        }catch(Exception e)
        {
            e.printStackTrace();
        }
    }
    
    public String receive()
    {
        try
        {
            DatagramPacket indp = new DatagramPacket(inBuff,inBuff.length);
            
            ms.receive(indp);
            String msg = new String(indp.getData(), 0, indp.getLength(), "GBK");
            return indp.getAddress() + "--->" + msg;
                
        }catch(Exception e)
        {
            return null;
           // e.printStackTrace();
        }
    }
    
    public void close()
    {
        try
        {
            ms.leaveGroup(groupIP);
            ms.close();
            
        }catch(Exception e)
        {
            e.printStackTrace();
        }
    }
}

你可能感兴趣的:(互联网程序设计第六讲)