网络编程-UDP协议、TCP协议

1.1 UDP协议特点

  • UDP是无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。简单来说,当一台计算机向另
    外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时,也不会向
    发送端反馈是否收到数据。
    由于使用UDP协议消耗资源小,通信效率高,所以通常都会用于音频、视频和普通数据的传输例如视频会议都使用
    UDP协议,因为这种情况即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。
    但是在使用UDP协议传送数据时,由于UDP的面向无连接性,不能保证数据的完整性,因此在传输重要数据时不建
    议使用UDP协议。UDP通信过程如下图所示:

  • UDP ==> User DatagramPacket Protocol ==> 用户数据报包协议
  • UDP协议的特点:(面试)
  1.  只管发送,不确认对方是否收到。
  2. 基于数据包(报)传输数据:将要发送的数据,接收端IP地址,端口号等信息打包到一个数据包中发送。
  3. 传输数据大小限制在64K以内。
  4. 速度快,但不可靠。(会出现数据丢失的情况)
  • UDP协议的使用场景:
  1. 即时通讯(qq,微信,陌陌)
  2. 在线视频
  3. 网络语音电话 
  • UDP协议通讯两个相关的类:
  • DatagramPacket
  1. 数据包对象
  2. 作用:用来封装要发送或接收的数据
  3. 比喻:集装箱
  • DatagramSocket
  1. 发送或接收对象
  2. 作用:用来发送数据包或接收数据包
  3. 比喻:码头
  • DatagramPacket类构造方法
  1. DatagramPacket(byte[] buf, int length, InetAddress address, int port)
  •  创建发送端的数据包对象
  • buf:字节数组,用来封装要发送的数据
  • length:要发送内容的长度 单位是:字节
  • address:接收端的IP地址对象
  • port:接收端的端口号
  1. port:接收端的端口号
  • 创建接收端的数据包对象
  • 创建接收端的数据包对象
  • length:能够接收内容的长度,单位:字节
  • DatagramSocket类构造方法
  • DatagramSocket()
  1. 创建发送端的Socket对象,随机生成一个端口号。
  • DatagramSocket(int port)
  1. 根据端口号创建Socket对象 
  • DatagramSocket类成员方法
  • void send(DatagramPacket dp) 发送数据包
  • void receive(DatagramPacket dp) 接收数据包 

 


 2.1 UDP通信案例

  • 需求:学生的电脑的一个程序发送数据,一个程序接收数据,使用的学生本机的ip。

UDP发送端代码实现:

import java.io.IOException;
import java.net.*;

public class UDPsend {
    public static void main(String[] args) throws Exception {
        //定义字符串:要发送的内容
        byte[] content = "我爱java".getBytes();

        //创建数据包对象:用来封装要发送的数据
        DatagramPacket dp = new DatagramPacket(content,content.length, InetAddress.getLocalHost(),8888);

        //创建发送对象:Socket对象
        DatagramSocket ds = new DatagramSocket();

        //发送数据包
        ds.send(dp);

        //关闭Socket释放端口号
        ds.close();
    }
}

UDP接收端代码实现:

import java.net.DatagramPacket;
import java.net.DatagramSocket;

/*
    UDP接收端代码实现
 */
public class UDPReceive {
    public static void main(String[] args) throws Exception{
        //创建接收端的Socket
        DatagramSocket ds = new DatagramSocket(8888);

        //创建字节数组,存储接收到的内容
        byte[] buf = new byte[1024];

        //创建数据包对象,用来封装接收到的数据
        DatagramPacket dp = new DatagramPacket(buf,buf.length);

        //接收数据包
        ds.receive(dp);

        //获得实际接收到的字节个数
        int len = dp.getLength();
        System.out.println("len="+len);

        // 将字节数组转换为字符串输出
        System.out.println(new String(buf,0,len));

        // 获取发送端的IP地址
        String sendIP = dp.getAddress().getHostAddress();

        // 获取发送端的端口号
        int sendPort = dp.getPort();
        System.out.println("sendIP="+sendIP);
        System.out.println("sendPort="+sendPort);

        //关闭Socket释放端口号
        ds.close();

    }
}

3.1 TCP协议概述

  • TCP协议是面向连接的通信协议,即在传输数据前先在客户端和服务器端建立逻辑连接,然后再传输数据。它
    提供了两台计算机之间可靠无差错的数据传输。TCP通信过程如下图所示: 

  • TCP协议的特点:(面试)
  1. 面向连接的协议
  2. 通过三次握手建立连接:形成数据传输通道。
  3. 通过四次挥手断开连接。
  4.  基于IO流进行数据传输。
  5. 传输数据大小没有限制。
  6. 速度慢但可靠的。
  • TCP协议的使用场景:
  1. 文件上传下载
  2. 邮件发送和接收
  3. 远程登录
  • TCP协议相当的两个类
  1. Socket:一个该类的对象就代表一个客户端程序
  2. ServerSocket:一个该类的对象就代表一个服务器端程序
  • Socket类构造方法
  • Socket(String host, int port)
  1.  根据服务器端IP地址和端口号创建客户端Socket对象
  2. host:服务器IP地址
  3. port:服务器端口号
  4. 注意:一旦执行该方法,就会立即连接指定的服务器,如果服务器没有开启,则连接失败抛出异常。
  • Socket类成员方法:
  1.  OutputStream getOutputStream(); 获得字节输出流对象
  2. InputStream getInputStream(); 获得字节输入流对象
  • ServerSocket类概述:一个该类的对象就代表一个服务器端程序
  • ServerSocket类构造方法:ServerSocket(int port)  
  1. 根据端口号创建服务器端Socket对象, 相当于开启了一个服务器
  • ServerSocket类成员方法:
  1. Socket accept() 等待客户端连接并获得与客户端相关的Socket对象

4.1 TCP通信案例

客户端向服务器发送数据

  • TCP客户端实现:
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

/*
    TCP客户端实现步骤:
    *创建Socket对象指定服务器端IP地址和端口号
    *调用Socket对象的getOutputStream方法获得字节输出流对象
    * 调用字节输出流对象的Write方法往服务器端输出数据
    * 调用Socket对象的getInputStream方法获得字节输入流对象
    * 调用字节输入流对象的read方法读取服务器端返回的数据
    * 关闭Socket对象断开连接
    * 127.0.0.1 本机IP地址
 */
public class TCPClient {
    public static void main(String[] args)throws Exception {
        //创建客户端Socket对象:相当于开启一个客户端程序
        Socket socket = new Socket("127.0.0.1",8888);
        System.out.println(socket);

        //获得字节输出流对象
        OutputStream out = socket.getOutputStream();

        //往服务器端输出数据
        out.write("约吗?".getBytes());

        //获得字节输入流对象
        InputStream in = socket.getInputStream();

        //定义字节数组:用来存储服务器返回的数据
        byte[] buf = new byte[1024];
        //读取服务器端返回的数据
        int len =in.read(buf);

        //输出服务器端返回的数据
        System.out.println("len="+len);
        System.out.println(new String(buf,0,len));

        //关闭Socket对象
        socket.close();

    }
}
  • TCP服务器端实现: 
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/*
    TCP服务器端代码实现步骤:
    * 创建ServerSocket对象并指定端口号
    * 调用ServiceSocket对象的accept方法等待客户端连接并获得与客户端相关的Socket对象
    * 调用Socket对象的getInputStream方法获得字节输入流对象
    * 调用字节输入流对象的read方法读取客户端发送的数据
    * 调用Socket对象的getOutputStream方法获取字节输出流对象
    * 调用字节输出流对象的write方法往客户端返回数据
    * 调用close方法关闭Socket和ServerSocket对象
 */
public class TCPService {
    public static void main(String[] args) throws Exception{
        //根据端口号创建服务器端Socket对象
        //相当于开启了一个服务器
        ServerSocket serverSocket = new ServerSocket(8888);

        //等待客户端连接并获得与客户端相关的Socket对象
        Socket socket = serverSocket.accept();
        System.out.println("-----------------");

        //获得字节输入流对象
        InputStream in = socket.getInputStream();
        //定义字节数组:用来存储客户端发送的数据
        byte[] buf = new byte[1024];
        //读取客户端返回数据
        int len = in.read(buf);
        System.out.println("len="+len);
        System.out.println(new String(buf,0,len));

        //获得字节输出流对象
        OutputStream out = socket.getOutputStream();
        //往客户端输出数据
        out.write("好的,约".getBytes());

        // 关闭socket
        socket.close();
        // 关闭serverSocket(实际开发中一般不会关闭服务器)
        serverSocket.close();
    }
}

  •  需求:使用TCP协议实现客户端和服务端互相发送消息。
  • 客户端发送一条消息,服务器读取之后,返回一条消息给客户端,客户端读取服务器返回的消息之后,又发送一条消息...循环执行,直到输入exit。
  1. 消息内容通过键盘录入。
  2. 要求服务器端和客户端都使用字符流的方式发送和接收数据。
  3. 使用BufferedReader方法readLine()读取一行数据。
  4. 使用BufferedWrite方法的Write(“字符串的数据”)发送数据。
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

/*
    TCP通讯服务器端
 */
public class TCPServer {
    public static void main(String[] args) {
        System.out.println("服务器启动......");
        try {
            //创建键盘录入对象
            Scanner sc = new Scanner(System.in);
            //创建服务器端Socket
            ServerSocket serverSocket = new ServerSocket(9999);

            //得到客户端对应的对象
            Socket socket = serverSocket.accept();

            //字符输入流
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            //字符输出流
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

            while (true){
                //接收对方的数据
                System.out.println("客户端说:"+br.readLine());
                System.out.println("我说:");
                String words = sc.nextLine();
                if ("exit".equals(words)) {
                    break;
                }
                //发送给对方
                bw.write(words);
                bw.newLine();
                bw.flush();
            }
            br.close();
            bw.close();
            socket.close();
            serverSocket.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
import java.io.*;
import java.net.Socket;
import java.util.Scanner;

/*
    TCP协议通讯客户端
 */
public class TCPClient {
    public static void main(String[] args) {

        try {
            //创建键盘录入对象
            Scanner sc = new Scanner(System.in);
            //根据服务器端的IP地址和端口号创建Socket对象
            Socket socket = new Socket("127.0.0.1",9999);

            //创建字符输入流对象
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            //创建字符输出流
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

            //输出数据
            //创建键盘录入对象
            while (true){
                System.out.println("我说:");
                //接收键盘录入的字符串
                String words = sc.nextLine();
                if("exit".equals(words)){
                    break;
                }
                    //发送数据
                    bw.write(words);
                    //换行
                    bw.newLine();
                    //一定要flush
                    bw.flush();
                    System.out.println("收到对方的数据:"+br.readLine());
                }
                br.close();
                bw.close();
                //关闭Socket
                socket.close();
        }catch (Exception e){
            e.printStackTrace();
        }

    }
}

猜你喜欢

转载自blog.csdn.net/Huangyuhua068/article/details/81610785