TCP、UDP的初步对比以及Java实现

通信协议

  • TCP:传输控制协议(传输层)
  • UDP:用户数据报协议(传输层)

网络模型

TCP协议

面向连接的通信协议,在传输数据前先建立发送端和接收端的逻辑链接

由于TCP协议的面向连接特性,它可以保证传输数据的安全性,所以是一个被广泛采用的协议,例如在下载文件时,如果数据接收不完整,将会导致文件数据丢失而不能被打开,因此,下载文件时必须采用TCP协议

特点:

  • 连接、稳定

  • 分为客户端、服务端

  • 传输完成,释放连接,效率低

  • 三次握手,四次分手

    三次握手:
    C:发送连接请求,等待服务器响应
    S:响应客户端请求,通知客户端收到了连接请求
    C:再次发送确认信息,确认链接
    
    四次挥手:
    C:发送断开请求,等待服务器相应
    S:响应客户端请求,通知收到断开请求
    S:发送断开请求,等待客户端相应
    C:确认服务器断开连接
    
    最少需要三次才能保证连接稳定!
    A:一起吃烧烤吗?
    B:好啊?
    A:那走吧!
    
    A:我要回家了
    B:那你走吧
    B:我也回家了
    A:拜拜
    
UDP协议

是无连接通信协议,在数据传输时,发送端和接收端不需要建立逻辑关系

由于使用UDP协议消耗资源小,通信效率高,所以通常都会用于音频、视频和普通数据的传输例如视频会议都使用UDP协议,因为这种情况即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。

但是在使用UDP协议传送数据时,由于UDP的面向无连接性,不能保证数据的完整性,因此在传输重要数据时不建议使用UDP协议。

  • 无连接、不稳定
  • 分为发送端、接收端,但没有明确的界限
  • 不管有没有准备好,都可以发送
  • DDOS:洪水攻击,占用网络,使网络连接瘫痪

TCP协议类似于打电话,发送方拨打电话,接收方接听电话,才能够进行通信
UDP协议类似于发短信,发送方仅需要发短信,不用确认是否连接成功

Java实现TCP通信

ServerSocket类
实现一个服务器端的程序
ServerSocket(int port),创建绑定到特定端口的服务器套接字

accept(),监听并接受此套接字的连接,阻塞式监听,返回一个Scoket对象用于和客户端实现通信
getInetAddress(),返回此服务器套接字的本地地址

Socket类
实现一个客户端的程序
Socket(String host,int port),创建一个套接字,并将其连接到指定主机的指定端口号
Sccket(InetAddress address,int port),创建一个套接字,并将其连接到指定IP地址的指定端口号

getInputStream(),返回输入流对象,用于读取接受到的数据
getOutputStream(),返回输出流对象,用于发送数据

C端的 OutPutStream 被B端的 InPutStream 接收
B端的 OutPutStream 被C端的 InPutStream 接收

客户端

  1. 创建客户端的Socket对象
  2. 获取Socket的输出流对象
  3. 写数据给服务器
  4. 通知服务器上传完毕
  5. 获取Socket的输入流对象
  6. 使用输入流,读反馈信息
  7. 关闭流资源
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;

public class TcpClientDemo02 {
    public static void main(String[] args) throws Exception {
        //1,构建 socket 链接
        Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),9000);
        //2,构建输出流
        OutputStream os = socket.getOutputStream();

        //3.文件流
        FileInputStream fis = new FileInputStream(new File("D:\\code\\Java\\网络编程\\test01.jpg"));

        //4、写出文件
        byte[] car = new byte[1024];
        int len;
        while ((len=fis.read(car))!=-1){
            os.write(car,0,len);
        }

        //通知服务器,上传完毕
        socket.shutdownOutput();
        //确定服务器接受完毕断开连接
        InputStream is = socket.getInputStream();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        while ((len = is.read(car))!=-1){
            baos.write(car,0,len);
        }

        System.out.println(baos.toString());

        //5,关闭资源
        baos.close();
        os.close();
        fis.close();
        socket.close();
    }
}

服务端

  1. 创建服务器端ServerSocket对象,指定服务器端端口号
  2. 开启服务器,等待着客户端Socket对象的连接,如有客户端连接,返回客户端的Socket对象
  3. 通过客户端的Socket对象,获取客户端的输入流,为了实现获取客户端发来的数据
  4. 通过客户端的输入流,获取流中的数据
  5. 通过客户端的Socket对象,获取客户端的输出流,为了实现给客户端反馈信息
  6. 通过客户端的输出流,写数据到流中
  7. 关闭流资源
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class tcpServerDemo02 {
    public static void main(String[] args) throws Exception{
        //1、构建一个 ServerSocket 对象 并指定端口号
        ServerSocket socket = new ServerSocket(8080);

        //2、监听客户端链接,获取客户端Socket对象,阻塞式监听,一直等待客户端连接
        Socket accept = socket.accept();

        //3、获得客户端的输入流
        InputStream is = accept.getInputStream();

        //4、获取输入流中的数据
        OutputStream fos = new BufferedOutputStream(new FileOutputStream(new File("D:\\code\\Java\\SE-kuang\\网络编程\\a.jpg")));
        byte[] car = new byte[1024];
        int len;
        while((len = is.read(car))!=-1){
            fos.write(car,0,len);
        }

        //5、通过客户端 Socket 对象,获得客户端的输出流
        OutputStream os = accept.getOutputStream();
        //6、通过输出流反馈信息
        os.write("文件上传成功,请关闭连接".getBytes());

        //7、关闭流资源
        os.close();
        fos.close();
        is.close();
        accept.close();
        socket.close();
    }
}

1.7、UDP通信

DatagramPacket类
用于封装UDP通信中传输的数据
接收端构造:DatagramPacket(byte[] buf,int length),构造Datagram,用来接收长度为 length 的数据
发送端构造:DatagramPacket(byte[] buf,int length,InetAddress address,int port),不仅指定了封装数据的字节数组和数据的大小,还指定了数据包的目标IP地址和端口号。

DatagramSocket类
构建DatagramPacket的发送端和接收端
发送端构造:DatagramSocket(),构造数据报套接字并绑定至本机任意可用端口上
接收/发送端构造:DatagramSocket(int port),构造数据报套接字,并绑定至本机指定端口上
在创建接收端 数据报套接字 时,必须指定一个端口号,这样才能够进行监听

receive(DatagramPacket),从此套接字中接收数据报包
send(DatagranPacket),从此套接字中 发送 数据报包

接收端:

  1. 创建DatagramSocket对象
  2. 创建DatagramPacket对象
  3. 接收数据存储到DatagramPacket对象中
  4. 获取DatagramPacket对象的内容
  5. 释放流资源
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class UdpServerDemo01 {
    public static void main(String[] args) throws Exception{
        //1、建立一个接收端的 DatagramSocket 对象
        DatagramSocket socket = new DatagramSocket(9090);

        //2、建立一个接收端的数据报包
        byte[] buf = new byte[1024];
        DatagramPacket packet = new DatagramPacket(buf, 0, buf.length);

        //3、接收数据报包
        socket.receive(packet);

        //4、获取数据报包中的内容
        String str = new String(buf,0,buf.length);
        System.out.println(str);

        //5、关闭资源
        socket.close();

    }
}

发送端:

  1. 创建DatagramSocket对象
  2. 创建DatagramPacket对象,并封装数据
  3. 发送数据
  4. 释放流资源
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class UdpclientDemo01 {
    public static void main(String[] args) throws Exception {
        //1、建立一个发送端的 DatagramSocket 对象
        DatagramSocket socket = new DatagramSocket();

        //2、建立一个需要发送的数据报包
        String str = new String("hello udp!");
        InetAddress localhost = InetAddress.getByName("localhost");
        DatagramPacket packet = new DatagramPacket(str.getBytes(),0,str.getBytes().length, localhost, 9090);

        //3、发送数据报包
        socket.send(packet);

        //4、关闭资源
        socket.close();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值