网络编程中的 TCP、UDP 了解一下

1. 网络编程

1.1 网络编程基础

1.1.1 目的

直接或间接地通过网络协议与其它计算机实现数据交换,进行通讯

1.1.2 问题

  1. 如何准确地定位网络上一台或多台主机:定位主机上的特定的应用(IP + 端口)
  2. 找到主机后,如何可靠、高效地进行数据传输(网络通信协议)

1.2 IP

IP:唯一的标识 Internet 上的计算机

IP 地址分类方式1:

  1. IPV4:4个字节组成。以“点分十进制”表示
  2. ​IPV6:16个字节组成。写成 8 个无符号整数,每个整数用四个十六进制位表示,数之间用冒号(:)表示

IP 地址分类方式2:

  1. 公网地址(万维网使用)

  2. 私有地址(局域网使用):192.168. 开头的就是私有地址(组织内部机构使用)

1.3 端口

端口被规定为一个16位的整数:0~65535

在同一主机中,不同的进程有不同的端口

端口被分为:

  1. 公认端口:0~1023。被预先定义的服务通信占用(如:HTTP 占用 80 端口、FTP 占用 21 端口)
  2. 注册端口:1024~49151。分配给用户进程或应用程序(如:Tomcat 占用 8080 端口、Mysql 占用 3306 端口)
  3. 动态/私有端口:49152~65535

Socket = IP + 端口

1.4 网络通信协议

网络协议太复杂,所以,将通信协议进行分层。

由上至下为:应用层、传输层(TCP、UDP)、网络层(IP)、数据链路层、物理层

TPC 与 UDP 的区别:

TCP 协议:

​         使用 TCP 协议前,必须先建立 TCP 连接,形成传输数据通道

​         传输前,采用“三次握手”方式,点对点通信,是可靠传输

​         TCP 协议进行通信的两个应用进程:客户端、服务端

​         在连接中,可进行大数据量的传输

​         传输完毕,需要释放已建立的连接(效率低)

UDP 协议:

​         将数据、源、目的封装成数据包,不需要建立连接

​         每个数据包的大小限制在 64k 内

​         发送不管对方是否准备好,接收方收到也不确认,不可靠传输

​         可以广播发送

​         发送数据结束时,无需释放资源(开销小、速度快)

1.5 TCP 网络编程

场景一:客户端通过 TCP 协议向服务端发送数据,服务端接收后,将收到的数据打印到控制台中,并指明来自于哪个客户端

public class TCPServer {

    public static void main(String[] args) throws Exception{
        // 指明需要监听的端口
        ServerSocket ss = new ServerSocket(1234);
        // 监听来自客户端的 Socket 请求
        Socket socket = ss.accept();
		// 获取 Socket 对象的输入流
        InputStream is = socket.getInputStream();

        // 如果客户端传来的是汉字(三个字节编码),使用字节流读取可能会存在乱码
        /*byte[] bytes = new byte[1024];
        int len = 0;
        while ((len = is.read(bytes)) != -1) {
            // 当把一个汉字劈成两半,再还原为字符串时就会乱码
            System.out.print(new String(bytes, 0 ,len));
        }*/

        // 创建一个字节数据输出流
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buffer = new byte[5];
        int len = 0;
        // 读取输入流中的数据
        while ((len = is.read(buffer)) != -1) {
            baos.write(buffer, 0 ,len);
        }
        System.out.println(baos.toString());
        System.out.println("收到了来自于:" + socket.getInetAddress().getHostAddress() + "的数据");

        baos.close();
        is.close();
        socket.close();
        ss.close();
    }
}
public class TCPClient {

    public static void main(String[] args) throws Exception{
        // 创建 Socket 对象,指明服务器的 ip 和端口
        Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 1234);
        // 通过 Socket 对象获取它的输出流
        OutputStream os = socket.getOutputStream();
        String data = "您好,我是客户端 GG";
        // 向服务器发送数据
        os.write(data.getBytes());

        os.close();
        socket.close();
    }
}

场景二:客户端将文件发送给服务端,服务端将文件保存起来

public class TCPServer2 {

    public static void main(String[] args) throws Exception{
        ServerSocket ss = new ServerSocket(1234);
        Socket socket = ss.accept();

        InputStream is = socket.getInputStream();
        FileOutputStream fos = new FileOutputStream(new File("2.jpg"));
        byte[] bytes = new byte[1024];
        int len = 0;

        while ((len = is.read(bytes)) != -1) {
            fos.write(bytes, 0 ,len);
        }

        fos.close();
        is.close();
        socket.close();
        ss.close();
    }
}
public class TCPClient2 {

    public static void main(String[] args) throws Exception{
        Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 1234);
        OutputStream os = socket.getOutputStream();

        FileInputStream fis = new FileInputStream(new File("1.jpg"));
        byte[] bytes = new byte[1024];
        int len = 0;
        while ((len = fis.read(bytes)) != -1) {
            os.write(bytes, 0, len);
        }

        fis.close();
        os.close();
        socket.close();
    }
}

场景三:客户端将文件发送给服务端,服务端将文件保存起来。并且,服务端需要返回“发送成功”给客户端,然后关闭相应连接

public class TCPServer3 {

    public static void main(String[] args) throws Exception{
        ServerSocket ss = new ServerSocket(1234);
        Socket socket = ss.accept();

        InputStream is = socket.getInputStream();
        FileOutputStream fos = new FileOutputStream(new File("2.jpg"));
        byte[] bytes = new byte[1024];
        int len = 0;

        while ((len = is.read(bytes)) != -1) {
            fos.write(bytes, 0 ,len);
        }

        // 服务端给予客户端反馈
        OutputStream os = socket.getOutputStream();
        String data = "发送成功";
        os.write(data.getBytes());

        fos.close();
        is.close();
        os.close();
        socket.close();
        ss.close();
    }
}
public class TCPClient3 {

    public static void main(String[] args) throws Exception{
        Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 1234);
        OutputStream os = socket.getOutputStream();

        FileInputStream fis = new FileInputStream(new File("1.jpg"));
        byte[] bytes = new byte[1024];
        int len = 0;

        // read() 方法是一个阻塞方法,没有明确指出传输完毕,就会一直阻塞
        while ((len = fis.read(bytes)) != -1) {
            os.write(bytes, 0, len);
        }

        // 给出明确指示(传输完毕)
        socket.shutdownOutput();

        // 客户端接收服务端传送过来的数据
        InputStream is = socket.getInputStream();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buffer = new byte[20];
        int length = 0;

        while ((length = is.read(buffer)) != -1) {
            baos.write(buffer, 0, length);
        }
        System.out.println(baos.toString());

        fis.close();
        os.close();
        baos.close();
        socket.close();
    }
}

1.6 UDP 网络编程

public class UDPReceiver {

    public static void main(String[] args) throws Exception {
        DatagramSocket socket = new DatagramSocket(1234);

        byte[] buffer = new byte[100];
        DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
        socket.receive(packet);
        System.out.println(new String(packet.getData(), 0, packet.getLength()));

        socket.close();
    }
}
public class UDPSender {

    public static void main(String[] args) throws Exception {
        DatagramSocket socket = new DatagramSocket();

        // 封装一个数据包(所有信息都在数据包中)
        String msg = "我是 UDP 发送方式的数据";
        byte[] data = msg.getBytes();
        DatagramPacket packet = new DatagramPacket(data, 0, data.length, InetAddress.getByName("127.0.0.1"), 1234);

        socket.send(packet);
        socket.close();
    }
}

1.7 URL 编程

URL:统一资源定位符。它表示 Internet 上某一资源的地址

URL的基本结构由5部分组成:

<传输协议>://<主机>:<端口号>/<文件名>#片段名?参数列表

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值