韩顺平Java39——网络编程

网络相关概念

客户端链接的时候构造器记得写IP+端口号

  • 网络通信:

 

 

  •  网络:

 

  •  IP地址:

 

 

 

 

 

 IPv6的地址长度为128位,是IPv4地址长度的4倍。于是IPv4点分十进制格式不再适用,采用十六进制表示。IPv6有3种表示方法。

win查看命令:ipconfig

 

  • 域名和端口号:

 

 

 

  •  网络通信协议

协议可以简单理解为数据的组织形式

 

  • TCP和UDP

 

 

 

 

三次握手(bushi)

 

 

 

 InetAddress类

 

 

package com.recorder.api;

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

/**
 * @author 紫英
 * @version 1.0
 * @discription
 */
public class Api_ {
    public static void main(String[] args) throws UnknownHostException {
        //1.获取本机的InetAddress对象
        InetAddress localHost = InetAddress.getLocalHost();
        System.out.println("本机的InetAddress对象: " + localHost);////2.根据指定主机名获取InetAddress对象
        InetAddress localHost2 = InetAddress.getByName("MrMRecorder");
        System.out.println("根据指定主机名获取InetAddress对象: " + localHost2);
        //3.根据域名获取InetAddress对象
        InetAddress baidu = InetAddress.getByName("www.baidu.com");
        System.out.println("根据域名www.baidu.com获取InetAddress对象: " + baidu);
        //4.通过InetAddress对象获取对应的地址
        String baiduAddress = baidu.getHostAddress();
        System.out.println("通过InetAddress对象获取对应的地址: " + baiduAddress);
        //5.通过InetAddress对象获取对应的主机名或域名
        String baiduName = baidu.getHostName();
        System.out.println("通过InetAddress对象获取对应的主机名或域名: " + baiduName);
    }
}

 

 

 

 

 

Socket

 

 

 

 

 

 TCP网络通信编程

  • 练习1:

 

 

思路分析:

 

  • 代码演示

服务器端:

package com.recorder.api.socket;

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

/**
 * @author 紫英
 * @version 1.0
 * @discription 服务端
 */
public class Tcp01Server {
    public static void main(String[] args) throws IOException {
//        1.在本机的9999端口监听,等待连接
//        注意:要求本机没有其他服务正在监听9999
//        注意:这个serverSocket可以通过serverSocket.accept()返回多个Socket,
//        即多个客户端链接服务器的并发
        ServerSocket serverSocket = new ServerSocket(9999);
        System.out.println("服务器端在9999端口监听,等待连接...");
//        2.当没有客户端连接9999端口时程序会阻塞,等待连接
//        如果有程序连接则会返回socket对象,程序继续
        Socket socket = serverSocket.accept();
        System.out.println("socket类型:" + socket.getClass());
//        3.通过 socket.getInputStream()读取客户端写入到数据通道的数据并显示
//            socket.getInputStream()
        InputStream inputStream =  socket.getInputStream();
//        4.IO读取
        byte[] bytes = new byte[1024];
        int readLen = 0;
        while ((readLen = inputStream.read(bytes)) != -1){
            System.out.println(new String(bytes,0,readLen)); //根据读取到的实际长度显示对应内容
        }
//        4.关闭对应的流和socket对象
            inputStream.close();
            socket.close();
            serverSocket.close();
            System.out.println("服务器端已退出!");

        }
    }

客户端:

package com.recorder.api.socket;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

/**
 * @author 紫英
 * @version 1.0
 * @discription 客户端
 */
public class Tcp01Client {
    public static void main(String[] args) throws IOException {
//        1.链接服务器端(ip,端口)
//        连接本机的服务器端,如果连接成功返回socket对象
//       (因为是演示连接本机,如果连接别的服务器则输入对应的ip地址)
        Socket socket = new Socket(InetAddress.getLocalHost(),9999);
        System.out.println("客户端socket返回:" + socket.getClass());

//        2.连接成功后生成socket对象,通过 socket.getOutputStream()
//        得到和socket对象关联的输出流对象
        OutputStream outputStream = socket.getOutputStream();
//        3.通过输出流写入数据到数据通道
        outputStream.write("hello,server!".getBytes());
//        4.关闭对应的流和socket对象
        outputStream.close();
        socket.close();
        System.out.println("客户端已退出!");

    }
}

 

 

 

  • 练习2:

 

 思路分析:

 

 服务器端:

package com.recorder.api.socket;

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

/**
 * @author 紫英
 * @version 1.0
 * @discription 服务端
 */
public class Tcp02Server {
    public static void main(String[] args) throws IOException {
//        1.在本机的9999端口监听,等待连接
//        注意:要求本机没有其他服务正在监听9999
//        注意:这个serverSocket可以通过serverSocket.accept()返回多个Socket,
//        即多个客户端链接服务器的并发
        ServerSocket serverSocket = new ServerSocket(9999);
        System.out.println("服务器端在9999端口监听,等待连接...");
//        2.当没有客户端连接9999端口时程序会阻塞,等待连接
//        如果有程序连接则会返回socket对象,程序继续
        Socket socket = serverSocket.accept();
        System.out.println("socket类型:" + socket.getClass());
//        3.通过 socket.getInputStream()读取客户端写入到数据通道的数据并显示
//            socket.getInputStream()
        InputStream inputStream = socket.getInputStream();
//        4.IO读取
        byte[] bytes = new byte[1024];
        int readLen = 0;
        while ((readLen = inputStream.read(bytes)) != -1) {
            System.out.println("客户端发来消息: " + new String(bytes, 0, readLen)); //根据读取到的实际长度显示对应内容
        }
//        5.向客户端发送消息
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("hello,client!".getBytes());
        socket.shutdownOutput();//设置结束标记

//        6.关闭对应的流和socket对象
        outputStream.close();
        inputStream.close();
        socket.close();
        serverSocket.close();
        System.out.println("服务器端已退出!");

    }
}

客户端:

package com.recorder.api.socket;

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

/**
 * @author 紫英
 * @version 1.0
 * @discription 客户端
 */
public class Tcp02Client {
    public static void main(String[] args) throws IOException {
//        1.链接服务器端(ip,端口)
//        连接本机的服务器端,如果连接成功返回socket对象
//       (因为是演示连接本机,如果连接别的服务器则输入对应的ip地址)
        Socket socket = new Socket(InetAddress.getLocalHost(),9999);
        System.out.println("客户端socket返回:" + socket.getClass());

//        2.连接成功后生成socket对象,通过 socket.getOutputStream()
//        得到和socket对象关联的输出流对象
        OutputStream outputStream = socket.getOutputStream();
//        3.通过输出流写入数据到数据通道
        outputStream.write("hello,server!".getBytes());
        socket.shutdownOutput(); 设置结束标记
//        4.接收服务器端的数据
        InputStream inputStream = socket.getInputStream();
        byte[] bytes = new byte[1024];
        int readLen = 0;
        while ((readLen = inputStream.read(bytes)) != -1) {
            System.out.println("服务器端发来消息: " + new String(bytes, 0, readLen)); //根据读取到的实际长度显示对应内容
        }



//        5.关闭对应的流和socket对象
        inputStream.close();
        outputStream.close();
        socket.close();
        System.out.println("客户端已退出!");

    }
}

 

 

练习3:

 

 思路分析:

 

 

服务器端:

package com.recorder.api.socket;

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

/**
 * @author 紫英
 * @version 1.0
 * @discription 服务端(字符流)
 */
@SuppressWarnings("all")
public class Tcp03Server {
    public static void main(String[] args) throws IOException {
//        1.在本机的9999端口监听,等待连接
//        注意:要求本机没有其他服务正在监听9999
//        注意:这个serverSocket可以通过serverSocket.accept()返回多个Socket,
//        即多个客户端链接服务器的并发
        ServerSocket serverSocket = new ServerSocket(9999);
        System.out.println("服务器端在9999端口监听,等待连接...");
//        2.当没有客户端连接9999端口时程序会阻塞,等待连接
//        如果有程序连接则会返回socket对象,程序继续
        Socket socket = serverSocket.accept();
        System.out.println("socket类型:" + socket.getClass());
//        3.读取客户端写入到数据通道的数据并显示
        InputStream inputStream = socket.getInputStream();
//        4.IO读取(字符流)
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String s = bufferedReader.readLine();
        System.out.println("客户端发来消息: " + s); //根据读取到的实际长度显示对应内容

//        5.向客户端发送消息
        OutputStream outputStream = socket.getOutputStream();
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
        bufferedWriter.write("hello,client!(字符流)");
        bufferedWriter.flush();
        bufferedWriter.newLine();//设置结束标记

//        6.关闭对应的流和socket对象
        bufferedWriter.close();
        bufferedReader.close();
        outputStream.close();
        inputStream.close();
        socket.close();
        serverSocket.close();
        System.out.println("服务器端已退出!");

    }
}

客户端:

package com.recorder.api.socket;

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

/**
 * @author 紫英
 * @version 1.0
 * @discription 客户端 (字符流)
 */
@SuppressWarnings("all")
public class Tcp03Client {
    public static void main(String[] args) throws IOException {
//        1.链接服务器端(ip,端口)
//        连接本机的服务器端,如果连接成功返回socket对象
//       (因为是演示连接本机,如果连接别的服务器则输入对应的ip地址)
        Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
        System.out.println("客户端socket返回:" + socket.getClass());

//        2.连接成功后生成socket对象,通过 socket.getOutputStream()
//        得到和socket对象关联的输出流对象
        OutputStream outputStream = socket.getOutputStream();
//        3.通过输出流写入数据到数据通道
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
        bufferedWriter.write("hello,server!(字符流)");
        bufferedWriter.newLine();//换行符——表示输入结束(要求对方使用readline!!!!)
        bufferedWriter.flush();//需要手动刷新
//        4.接收服务器端的数据
        InputStream inputStream = socket.getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String s = bufferedReader.readLine();
        System.out.println("服务器端发来消息: " + s);

//        5.关闭对应的流和socket对象
        bufferedReader.close();
        bufferedReader.close();
        inputStream.close();
        outputStream.close();
        socket.close();
        System.out.println("客户端已退出!");

    }
}

 

练习4:

 

 

 思路分析:

 

 

 服务器端:

package com.recorder.api.upload;

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

/**
 * @author 紫英
 * @version 1.0
 * @discription 文件上传服务器端
 */
public class TcpFileUploadServer {
    public static void main(String[] args) throws Exception {
        String filePath = "src\\pic.jpg";
//        1.服务器端在本机监听8888端口
        ServerSocket serverSocket = new ServerSocket(8888);
        System.out.println("监听8888端口等待客户端连接...");
//        2.等待连接
        Socket socket = serverSocket.accept();
//        3.创建输入流读取客户端发来的数据
        BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
        byte[] bytes = SteamUtil.streamToByteArray(bis);
//        4.将得到的字节数组写入到指定文件路径,得到文件
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath));
        bos.write(bytes);
        bos.close();

//        5.向客户端发送:收到图片
//socket获取输出流
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        writer.write("收到图片!");
        writer.flush();//把内容刷新到数据通道
        socket.shutdownOutput();//设置结束标记

        //关闭其他流
        writer.close();
        bis.close();
        socket.close();
        serverSocket.close();
        System.out.println("服务器端关闭!");



    }
}

客户端:

package com.recorder.api.upload;

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

/**
 * @author 紫英
 * @version 1.0
 * @discription 文件上传客户端
 */
public class TcpFileUploadClient {
    public static void main(String[] args) throws Exception {
//        1.客户端连接服务器端8888端口,得到socket对象
        Socket socket = new Socket(InetAddress.getLocalHost(), 8888);
//        2.创建读取图片文件的输入流
        String filePath = "e:\\wu.jpg";
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath));
        byte[] bytes = SteamUtil.streamToByteArray(bis); //这里的字节数组存放的就是对应的文件内容
//        3.通过socket获取输出流将数据(字节数组)发送给服务器端
        BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
        //将文件对应的字节数组内容写入到数据通道
        bos.write(bytes);
        //设置结束标记
        socket.shutdownOutput();
        bis.close();

//        4.接收服务器端发送的消息
        InputStream inputStream = socket.getInputStream();
        //使用工具类将InputStream转化为String
        String s = SteamUtil.streamToString(inputStream);
        System.out.println("服务器端发来消息:" + s);

        //关闭对应的流
        socket.close();
        bos.close();
        inputStream.close();
        System.out.println("客户端关闭!");

    }
}

工具类:

package com.recorder.api.upload;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;

/**
 * @author 紫英
 * @version 1.0
 * @discription 将输入流转换为byte[]
 */
public class SteamUtil {

    public static byte[] streamToByteArray(InputStream is) throws  Exception{
        ByteArrayOutputStream bos = new ByteArrayOutputStream();//创建输出流对象
        byte []b = new byte[1024]; //字节数组——读取输入流
        int len;
        while ((len = is.read(b))!= -1){
            bos.write(b,0,len); //把读取到的数据写入到字节数组流
        }
        byte[] array = bos.toByteArray(); //将bos转为字节数组
        bos.close();
        return array;
    }

    public  static  String streamToString(InputStream is) throws Exception{
        //将输入流数据转换为String
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuffer buffer = new StringBuffer();
        String line = null;
        while ((line = reader.readLine())!=null){
            buffer.append(line + "\r\n");
        }
        return buffer.toString();
    }

}

 

netstat命令

 

 

 这里127.0.0.1 和 0.0.0.0都表示本机

外部地址表示有没有外部的链接连接到本机,显示的是连接到本机的外部链接的ip地址和端口号

状态:LISTRNING表示正在监听  ESTABLING表示已连接

-anb参数可以查看是哪个程序正在监听(需要管理员身份)

 

 

 

  • 冷知识

 

 

 

 

 

 UDP网络通信编程(了解)

 

 

 

 

 

 

 

 

 

 

  • 练习1:

 

 

 

 receiver端:

package com.recorder.api.udp;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.nio.charset.StandardCharsets;

/**
 * @author 紫英
 * @version 1.0
 * @discription 接收端
 */
public class UdpReceiver {
    public static void main(String[] args) throws IOException {
        //1.创建一个DatagramSocket对象,在9999端口等待接收数据
        DatagramSocket datagramSocket = new DatagramSocket(9999);
//        2.创建一个DatagramPacket对象接收数据(一个数据包最大64KB)
        byte[] bytes = new byte[1024];
        DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length);
//        3.调用接收方法,将通过网络传输的DatagramPacket对象填充到datagramSocket中
        System.out.println("receiver等待接收数据...");
//        当没有数据发送到9999本机的端口时就会阻塞等待
        datagramSocket.receive(datagramPacket);
//        4.对datagramPacket进行拆包取出数据并展示
        int len = datagramPacket.getLength();
        byte[] b = datagramPacket.getData();
        String s = new String(b,0,len);
        System.out.println("sender发来消息:" + s);

//        5.向sender端发送消息
        byte[] data = "下次一定!".getBytes(StandardCharsets.UTF_8);
        DatagramPacket packet = new DatagramPacket(data, data.length,
                InetAddress.getByName("192.168.47.1"), 9998);
        datagramSocket.send(packet);


//        关闭资源
        datagramSocket.close();
        System.out.println("receiver端退出");

    }
}

sender端:

package com.recorder.api.udp;

import java.io.IOException;
import java.net.*;
import java.nio.charset.StandardCharsets;

/**
 * @author 紫英
 * @version 1.0
 * @discription 发送端
 */
public class UdpSender {
    public static void main(String[] args) throws IOException {
        //1.创建一个DatagramSocket对象,在9998端口等待接收数据
        DatagramSocket datagramSocket = new DatagramSocket(9998);
//        2.将需要发送的数据封装到DatagramPacket对象
        byte[] data = "hello 明天出来玩!".getBytes(StandardCharsets.UTF_8);
        DatagramPacket packet = new DatagramPacket(data, data.length,
                InetAddress.getByName("192.168.47.1"), 9999);
        datagramSocket.send(packet);

        byte[] bytes = new byte[1024];
        DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length);
//        3.调用接收方法,将通过网络传输的DatagramPacket对象填充到datagramSocket中
        System.out.println("receiver等待接收数据...");
//        当没有数据发送到9999本机的端口时就会阻塞等待
        datagramSocket.receive(datagramPacket);
//        4.对datagramPacket进行拆包取出数据并展示
        int len = datagramPacket.getLength();
        byte[] b = datagramPacket.getData();
        String s = new String(b,0,len);
        System.out.println("receiver端发来消息:" + s);

        //关闭资源
        datagramSocket.close();
        System.out.println("sender端退出");


    }
}

 

posted @ 2022-01-31 14:14  紫英626  阅读(126)  评论(0编辑  收藏  举报

紫英