Java网络编程

1. IP地址

  1. 唯一标识网络中的每台主机
  2. 查看IP地址,ipconfig
  3. ip地址表示形式: 点分十进制 xx.xx.xx IPV4:4个字节32位,一个字节范围0~255, IPV6,16个字节,ipv6解决网络地址资源数量的问题,也解决了多种接入设备连入互联网的障碍,IPV6还没完全替代IPV4
  4. ip地址组成=网络地址+主机地址,192.168.16.69 192.168.16为网络地址
    在这里插入图片描述

ipv4分类

6. [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B9Rm0Pv5-1684848230131)(E:\新建文件夹\java\image\网络\IPV4分类.png)]

2. 域名和端口

域名:

  1. 为方便记忆,解决记IP的困难
  2. 概念:将ip地址映射成域名, HTTP协议映射

端口号:

  1. 概念:用于标识计算机上某个特定的网络程序
  2. 表示形式:以整数形式,范围 0~065535
  3. 0~1024已经被占用,比如ssh 22, ftp 21, smtp 25, http 80
  4. 常见的网络程序端口号: tomcat:8080 mysql:3306 oracle:1521 sqlserver:1433
    域名和端口

3. 网络协议

在这里插入图片描述
在这里插入图片描述

TCP/IP (Transmission Control Protocol / Internet Protocol)的简写,中文译名为传输控制协议/因特网互联协议,又叫网络通讯协议

TCP协议

  1. 使用TCP协议前,须先建立TCP连接,形成传输数据通道
  2. 传输前,采用“三次握手"方式,是 == 可靠 == 的
  3. TCP协议进行通信的两个应用进程:客户端、服务端
  4. 在连接中可进行大数据量传输
  5. 传输完毕,需释放已建立的连接,效率低

UDP协议

  1. 将数据、源、目的封装成数据包,不需要建立连接
  2. 每个数据报的大小限制在64K内,不适合传输大量数据
  3. 因无需连接,故是不可靠
  4. 发送数据结束时无需释放资源(因为不是面向连接的),速度快
  5. 举例:厕所通知:发短信

4. InetAddress

  1. 获取本机InetAddress对象InetAddress getLocalHost()

  2. 根据指定主机名/域名获取ip地址对象String getByName()

  3. 获取InetAddress对象的主机名String getHostName()

  4. 获取InetAddress对象的地址InetAddress getHostAddress()

import java.net.InetAddress;
import java.net.UnknownHostException;

public class InetAddress_ {
    public static void main(String[] args) throws UnknownHostException {
        InetAddress localHost = InetAddress.getLocalHost();
        System.out.println(localHost);
        InetAddress host2 = InetAddress.getByName("WIN-9CPMVKSG0CV");
        System.out.println(host2);

        InetAddress host3= InetAddress.getByName("www.baidu.com");
        System.out.println(host3);
        String hostname = host3.getHostName();
        System.out.println(hostname);
        String hostAddress = host3.getHostAddress();
        System.out.println(hostAddress);
    }
}
/*
WIN-9CPMVKSG0CV/192.168.10.9
WIN-9CPMVKSG0CV/192.168.10.9
www.baidu.com/39.156.66.18
www.baidu.com
39.156.66.18

5. Socket

  1. 套接字(Socket)开发网络应用程序被广泛采用,以至于成为事实上的标准。
  2. 通信的两端都要有Socket,是两台机器间通信的端点
  3. 网络通信其实就是Socket间的通信。
  4. Socket:允许程序把网络连接当成一个流,数据在两个Socketl间通过O传输。
  5. 一般主动发起通信的应用程序属客户端,等待通信请求的为服务端
    在这里插入图片描述

TCP字节流编程

需求:

  1. 编写一个服务端,和一个客户端
  2. 服务端在9999端口监听
  3. 客户端连接到服务端,发送"hello,server",并接收服务端回发的"helo,client",再退出
  4. 服务端接收到客户端发送的信息,输出,并发送"hello,client",再退出
    在这里插入图片描述

输出一定要设置结束标志socket.shutdownOutput();

服务端

package wjx.com.socket;


import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

//客户端,发送 ”hello,world“ 给服务端
public class SocketClient {
    public static void main(String[] args) throws IOException {
//        连接服务端(ip,端口)
//        连接InetAddress.getLocalHost()的9999端口,连接成功返回socket对象
        Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
        System.out.println("客户端连接成功 socket"+socket.getClass());
//
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("hello, world".getBytes());
        socket.shutdownOutput();
        InputStream inputStream = socket.getInputStream();
        byte[] buf = new byte[1024];
        int readlen = 0;
        while ((readlen = inputStream.read(buf))!=-1){
            System.out.println(new String(buf, 0, readlen));
        }


        outputStream.close();
        inputStream.close();
        socket.close();
        System.out.println("客户端退出");
    }
}
/*
客户端连接成功 socketclass java.net.Socket
hello,client
客户端退出

客户端

package wjx.com.socket;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

//主机,服务端
public class SocketServer {
    public static void main(String[] args) throws IOException {
//        在本机9999端口监听,等待连接
//        本机没有其他服务监听9999
//        ServerSocket可以通过accept返回多个socket[],高并发
        ServerSocket serverSocket = new ServerSocket(9999);
        System.out.println("监听9999端口,等待连接");
//        没有客户端连接时,程序阻塞,等待连接
//         如果有客户端连接,则返回Socket对象,程序继续
        Socket socket = serverSocket.accept();
        System.out.println("服务端连接成功 socekt" + socket.getClass());

        InputStream inputStream = socket.getInputStream();

        byte[]  buf = new byte[1024];
        int readlen = 0;
        while ((readlen = inputStream.read(buf))!=-1){
            System.out.println(new String(buf, 0, readlen));
        }

        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("hello,client".getBytes());
        socket.shutdownOutput();

        inputStream.close();
        outputStream.close();
        socket.close();
        serverSocket.close();
    }
}
/*
监听9999端口,等待连接
服务端连接成功 socektclass java.net.Socket
hello, world

TCP字符流编程

将socket得到的字节输入输出流包装成字符输入输出流

BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));

之后需要通过flush进行写入

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));

package wjx.com.socket;

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

public class SocketServerchar {
    public static void main(String[] args) throws IOException {
//        在本机9999端口监听,等待连接
//        本机没有其他服务监听9999
//        ServerSocket可以通过accept返回多个socket[],高并发
        ServerSocket serverSocket = new ServerSocket(9999);
        System.out.println("监听9999端口,等待连接");
//        没有客户端连接时,程序阻塞,等待连接
//         如果有客户端连接,则返回Socket对象,程序继续
        Socket socket = serverSocket.accept();
        System.out.println("服务端连接成功 socekt" + socket.getClass());

        InputStream inputStream = socket.getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String str = bufferedReader.readLine();
        System.out.println(str);

        OutputStream outputStream = socket.getOutputStream();
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
        bufferedWriter.write("hello,client");
        bufferedWriter.flush();
        socket.shutdownOutput();

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

TCP传文件

  1. 编写一个服务端,和一个客户
  2. .服务器端在8888端口监听
  3. 客户端连接到服务端,发送一张图片e:\\photo.webp
  4. 服务器端接收到客户端发送的图片,保存到src下,发送"收到图片"再退出
  5. 客户端接收到服务端发送的“收到图片”,再退出
    在这里插入图片描述

工具类

package wjx.com.socket;

import java.io.*;

public class Utils_IO {

    public static byte[] streamToByte(InputStream is) throws IOException {
        ByteArrayOutputStream bao = new ByteArrayOutputStream();
        byte[] b = new byte[1024];
        int readlen = 0;
        while((readlen=is.read(b))!=-1){
            bao.write(b, 0, readlen);
        }
        byte[] buf = bao.toByteArray();
        bao.close();
        return buf;
    }

    public  static String streamToString(InputStream is) throws IOException {
        BufferedReader bfr = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder() ;
        String len = "";
        while((len = bfr.readLine())!=null){
            sb.append(len);
        }
        return sb.toString();
    }
}

服务端

package wjx.com.socket;

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

public class FileServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8888);
        System.out.println("服务端等待连接");
        Socket socket = serverSocket.accept();

        BufferedInputStream bfi = new BufferedInputStream(socket.getInputStream());
        byte[] buf = Utils_IO.streamToByte(bfi);


        String filepath = "E:\\photocopy.webp";
        BufferedOutputStream bfo = new BufferedOutputStream(new FileOutputStream(filepath));
        bfo.write(buf);

        BufferedWriter bfw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        bfw.write("收到图片");
        bfw.flush();
        socket.shutdownOutput();

        bfw.close();
        bfo.close();
        bfi.close();
        socket.close();
        serverSocket.close();
        System.out.println("服务端关闭");
    }
}
/*
服务端等待连接
服务端关闭

客户端

package wjx.com.socket;

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

public class FileClient {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket(InetAddress.getLocalHost(),8888);
        System.out.println("客户端连接成功");

        String filepath = "E:\\photo.webp";
        BufferedInputStream bfi = new BufferedInputStream(new FileInputStream(filepath));
//        将文件转换成字符数组
        byte[] buf = Utils_IO.streamToByte(bfi);


//          获取socket输出流,将文件上传,写入数据通道
        BufferedOutputStream bfo = new BufferedOutputStream(socket.getOutputStream());
        bfo.write(buf);
        socket.shutdownOutput();

        String s = Utils_IO.streamToString(socket.getInputStream());
        System.out.println(s);

        bfo.close();
        bfi.close();
        socket.close();
        System.out.println("客户端关闭");
    }
}
/*
客户端连接成功
收到图片
客户端关闭

netstat

netstat -an 可以查看当前主机网络情况,包括端口监听情况和网络连接情况

TCP连接秘密

当客户端连接到服务端后,实际上客户端也是通过一个端口和服务端进行通讯的,这个端口是TCP/IP来分配的,是不确定的,是随机的
在这里插入图片描述

6.UDP

在这里插入图片描述

UDP介绍

  1. 没有明确的服务端和客户端,演变成数据的发送端和接收端
  2. 接收数据和发送数据是通过DatagramSocket对像完成,
  3. 将数据封装到DatagramPacket对像/装包
  4. 当接收到DatagramPacket对象,需要进行拆包,取出数据
  5. DatagramSocket可以指定在哪个端口接收数据

UDP流程

  1. 核心两个类/对象 DatagramSocket与DatagramPacket
  2. 建立发送端,接收端(没有服务端和客户端概念
  3. 发送数据前,建立数据包/报 DatagramPacket对象
  4. 调用DatagramSocket的发送方法,接受方法
  5. 关闭DatagramSocket
    在这里插入图片描述
package wjx.com.socket.UDP;

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


public class UDPSender {
    public static void main(String[] args) throws IOException {
//        创建DatagramSocket对象,在9998端口接收数据
        DatagramSocket socket = new DatagramSocket(9998);

//        封装的 DatagramPacket 对象 bytes内容字节数组 , bytes.length , 主机(IP) , 端口
        byte[] bytes = "hello,明天吃火锅".getBytes();
        DatagramPacket packet
                = new DatagramPacket(bytes,0,bytes.length, InetAddress.getByName("192.168.10.9"),9999);
        socket.send(packet);

        
        byte[] bytes1 = new byte[1024];
        DatagramPacket packet1 = new DatagramPacket(bytes1, bytes1.length);

        socket.receive(packet1);
        int length = packet1.getLength();
        byte[] data = packet1.getData();
        String str = new String(data, 0, length);
        System.out.println(str);

        socket.close();
        System.out.println("B端退出");
    }
}
/*
好的
B端退出
package wjx.com.socket.UDP;

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

public class UDPServer {
    public static void main(String[] args) throws IOException {
        DatagramSocket socket = new DatagramSocket(9999);

        byte[] bytes = new byte[1024];
        DatagramPacket packet = new DatagramPacket(bytes,bytes.length);
        //3. 调用 接收方法, 将通过网络传输的 DatagramPacket 对象
        // 填充到 packet 对象
        //当有数据包发送到 本机的 9999 端口时,就会接收到数据
        // 如果没有数据包发送到 本机的 9999 端口, 就会阻塞等待
        System.out.println("A端等待接收数据");
        socket.receive(packet);
//        拆包
        int length = packet.getLength();
        byte[] data = packet.getData();
        String str = new String(data, 0, length);
        System.out.println(str);
        System.out.println("A端退出");

        
        byte[] bytes1 = "好的".getBytes();
        DatagramPacket packet1 =
                new DatagramPacket(bytes1, bytes1.length, InetAddress.getByName("192.168.10.9"),9998);
        socket.send(packet1);

        socket.close();
    }
}
/*
A端等待接收数据
hello,明天吃火锅
A端退出

7.TCP文件下载

在这里插入图片描述

流程:

  1. 客户端向端口传输需要下载的文件名
  2. 服务端接听文件名
  3. 寻找磁盘中是否有该文件,如果有,则使用该文件,没有则使用默认文件
  4. 将得到的文件转换为字节数组
  5. 将字节数组放到数据通道中
  6. 客户端拿到字节数组
  7. 创建和文件关联的输出流,将字节数组输出到文件

服务端

package wjx.com.socket.FileLoad;

import wjx.com.socket.TCP.Utils_IO;

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

public class Server_1 {
    public static void main(String[] args) throws IOException {
//        监听端口
        ServerSocket serverSocket = new ServerSocket(9999);
        System.out.println("服务端等待连接");
//        得到连接
        Socket socket = serverSocket.accept();
//        输入流,读取用户要下载的文件名
        InputStream inputStream = socket.getInputStream();
        byte[] bytes = new byte[1024];
        int len = 0;
        String loadFileName = "";
        while ((len=inputStream.read(bytes))!=-1){
            loadFileName += new String(bytes, 0, len);
        }
        System.out.println("申请下载的文件名为:"+loadFileName);
//        判断是否为grils.png 是则为grils.png 若不是,则设为默认的ikun.png
        String str = "";
        if("girl".equals(loadFileName)){
            str = "src\\girl.png";
        }else{
            str = "src\\ikun.png";
        }
//        得到文件的字节数组
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(str));

        ByteArrayOutputStream bao = new ByteArrayOutputStream();
        byte[] b = new byte[1024];
        int readlen = 0;
        while((readlen=bis.read(b))!=-1){
            bao.write(b, 0, readlen);
        }
        byte[] buf = bao.toByteArray();
        bao.close();

//        将文件字节数组写入通道
        BufferedOutputStream bos =
                new BufferedOutputStream(socket.getOutputStream());
        bos.write(buf);
        socket.shutdownOutput();
//        关闭资源
        serverSocket.close();
        socket.close();
        inputStream.close();
        bis.close();
        bos.close();
        System.out.println("服务端关闭");


    }
}
package wjx.com.socket.FileLoad;

import wjx.com.socket.TCP.Utils_IO;

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

public class Client_1 {
    public static void main(String[] args) throws IOException {
//        获得用户需要下载的资源
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入你想要下载的资源:");
        String fileName = scanner.next();

        Socket socket = new Socket(InetAddress.getLocalHost(), 9999);

        OutputStream outputStream = socket.getOutputStream();
        outputStream.write(fileName.getBytes());
        socket.shutdownOutput();

        BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());

        ByteArrayOutputStream bao = new ByteArrayOutputStream();
        byte[] b = new byte[1024];
        int readlen = 0;
        while((readlen=bis.read(b))!=-1){
            bao.write(b, 0, readlen);
        }
        byte[] buf = bao.toByteArray();
        bao.close();


        String filepath = "src\\"+fileName+".png";
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filepath));
        bos.write(buf);

        socket.close();
        outputStream.close();
        bis.close();
        bos.close();
        System.out.println("客户端退出");

    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值