网络TCP/UDP

本文详细介绍了Java中的网络通信包,包括TCP和UDP协议的工作原理,如TCP的三次握手和数据传输的可靠性,以及UDP的高效但不可靠的特性。还探讨了InetAddress类用于获取IP和主机名的方法,以及Socket在TCP和UDP编程中的应用,展示了服务器端和客户端的示例代码。

网络通信包java.net

各种类,枚举,异常
网络分为 局域 城域 广域网

端口

标识计算机上某个特定的网络程序
整数形式表示 0-65535
0-1024已经被占用了
mysql 3306
tomcat 8080
Oracle 1521
sqlserver 1433

协议

数据的组织形式就是协议
交互时,两个设备需要使用相同的协议才能实施通信
TCP/IP transmission control protocol
数据进入协议栈时的封装过程 图如下
在这里插入图片描述
一步一步封包然后发出

应用层 上图整体是
传输层 从TCP开始(不仅仅只有TCP协议一种)
网络层 从IP开始
物理 数据链路层 加了针头针尾

TCP与UTP协议

TCP传输控制协议

  1. 使用前需要建立TCP连接
  2. 传输前需要三次握手
  3. 两个应用进程:客户端/服务端
  4. 可以大数据量传输
  5. 使用完后需要关闭,效率低

TCP与UDP有各自自己的优势
TDP大数据量,但是是单线程,使用完还需要释放连接,可靠
UTP小数据量,但是可以多发,不确定能否送达,不可靠

UDP用户数据协议

  1. 数据 源 目的 封装成数据包,不需要建立连接
  2. 数据包大小在64k内,不适合大数据量
  3. 无需连接,不可靠,不一定成功
  4. 发送数据结束时无需释放资源,不做连接,速度块

InetAddress类

常用方法

  1. getLocalHost获取本机InetAddress对象
  2. getByName 获取指定主机/域名IP地址对象
  3. getHostName 获取InetAddress对象的主机名
  4. getHostAddress 获取InetAddress对象的地址
    public static void main(String[] args) throws UnknownHostException {
        InetAddress localHost = InetAddress.getLocalHost();
        System.out.println(localHost.toString());
        System.out.println(InetAddress.getByName("LAPTOP-70S2DNEN"));
        System.out.println(InetAddress.getByName("www.baidu.com"));
        System.out.println(localHost.getHostAddress());
        System.out.println(localHost.getHostName());
        InetAddress qqInetBean = InetAddress.getByName("qq.com");
        System.out.println(qqInetBean.getHostName());

    }

在这里插入图片描述

Socket 插座/接口

通过Socket拿到管道的输入输出流,可以进行数据读取操作
发起连接属于客户端 向 监听 接收请求连接 属于 服务端

两边都有Socket套接字
当需要通讯时(读写数据),通过Socket两个方法socket.getOutputStream() /Input
两端都有Socket对象,两端都有这两个方法
比如客户端发数据给服务端,客户端使用Output,服务端使用Input即可

Socket有两种编程

  1. TCP 可靠大数据
  2. UDP 不可靠少数据
    在这里插入图片描述
    对应地址和端口,建立连接,进行数据传输,最后close
编写服务器端和客户端

服务器监听9999端口
客户端连接到服务器端,并发送 数据内容
服务端收到客户端的 数据内容 并输出

UDP网络通信编程

  1. 类DatagramSocket数据包 / DatagramPacket数据报 实现了UTP协议网络程序
  2. 通过数据报套接字 DatagramSocket 发送和接收
  3. DatagramPacket对象封装了UDP数据报,在数据报中包含了发送端/接收端的IP和端口号
  4. UDP协议包含了双方的完整地址信息,无需建立连接
  5. 注意一个数据报只能传送64个k内

建立发送端,接收端 DatagramSocket>封装数据包DatagramPacket>发送

  • 传输是通过Socket,封装是Packet
  • 收到包后需要拆包得到数据
  • Socket可以指定监听哪个端口
    在这里插入图片描述
    DatagramSocket常用方法
  1. receive 监测端口 需要带datagramPacket对象//在此代码中堵塞
  2. send发送包 需要带datagramPacket对象

A端,接收端,先接收再回复

package com.lgj.UDP_;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;

public class UDPReceiverA {
    public static void main(String[] args) throws IOException {
        DatagramSocket datagramSocket = new DatagramSocket(9999);
        byte[] bytes = new byte[1024];//byte存放的是数据报,不仅仅只有数据本身,所以需要拆包
        DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length);
        datagramSocket.receive(datagramPacket);//线程在此处阻塞

        //此时抓到包,准备拆包
        byte[] data = datagramPacket.getData();
        int length = datagramPacket.getLength();
        String s = new String(data, 0, length);//data字节数组,0偏移量,实际长度
        System.out.println(s);

        byte[] bytes1 = "OK,see you tomorrow".getBytes();
        //发送回应包
        datagramSocket.send(new DatagramPacket(bytes1,bytes1.length,InetAddress.getLocalHost(),9998));
        
        datagramSocket.close();
    }
}

B端,先发信,再接收

package com.lgj.UDP_;

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

public class UDPSenderB {
    public static void main(String[] args) throws IOException {
        DatagramSocket datagramSocket = new DatagramSocket(9998);//在9998中接收数据与   标记发出数据地址
        //创建端口是给自己的传菜口,同一台机子上不能相同的,不然进出盘子在同一个地方

        byte[] bytes = ("B说 A老弟,明天吃火锅".getBytes());
        DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length, InetAddress.getLocalHost(), 9999);
        //现在指定目标的ip,目标的端口
        //封包结束,准备发
        datagramSocket.send(datagramPacket);


        //准备接收回应包,并拆
        byte[] bytes1 = new byte[1024];
        DatagramPacket datagramPacket1 = new DatagramPacket(bytes1, bytes.length);
        datagramSocket.receive(datagramPacket1);//线程阻塞

        //接收到回应包,拆包!
        byte[] data = datagramPacket1.getData();
        int length = datagramPacket1.getLength();
        String s = new String(data, 0, length);
        System.out.println(s);


        datagramSocket.close();

    }
}

TCP练习

客户端 向 服务端 发信
服务端接收到信息,并对信息分析,做出回应
若是收到name ,则输出名字,若是 其他,则输出 你在说什么

需要注意的地方:

  1. 输出流输出结束后要通过newLine标记结束,并且需要使用flush推出信息
  2. 使用完毕后按顺序关流

服务端

package com.lgj.Homeworke01Server;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(9996);
        Socket socket = serverSocket.accept();
        System.out.println("有客户端接入!");

        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));

        boolean loop = true;
        while (loop){
            String s = bufferedReader.readLine();
            System.out.println(s);

            switch (s) {
                case "name":
                    bufferedWriter.write("我是黄明俊");
                    break;
                case "hobby":
                    bufferedWriter.write("写java,跑步");
                    break;
                case "break":
                    bufferedWriter.write("再见!");
                    break;
                default:
                    bufferedWriter.write("你说神麽?");

            }
            bufferedWriter.newLine();
            bufferedWriter.flush();

            if (s.equals("break")) {
                loop = false;
            }

        }
        bufferedWriter.close();
        bufferedReader.close();
        socket.close();
        serverSocket.close();

    }
}

客户端

package com.lgj.Homeworke01Server;

import javafx.scene.effect.Bloom;

import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;

public class Client {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket(InetAddress.getLocalHost(), 9996);
        System.out.println("连接成功");
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        Scanner scanner = new Scanner(System.in);

        boolean loop = true;
        while (loop) {
            String s = scanner.nextLine();

            if (s.equals("break")) {
                loop = false;
            }

            bufferedWriter.write(s);
            bufferedWriter.newLine();
            bufferedWriter.flush();

            String s1 = bufferedReader.readLine();
            System.out.println(s1);
        }

        bufferedReader.close();
        bufferedWriter.close();
        socket.close();
    }
}

UDP练习

接收端A 发送端B
接收端在8888端口监听
发送端发送 四大名著是哪些
接收端收到问题后,返回 四大名著是红楼梦,否则返回what?

接收端

  1. 监听端口接收包
  2. 收包后拆包 拿内容判断回复什么
  3. 封包发送,发送的地址和端口通过第一步的接受包拆出来

TCP文件传输作业

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值