21章 网络编程

 

目录

IP

TCP/IP协议

netStat 指令  :查看网络状况

TCP和UDP协议

UDP(了解即可)

​编辑

Socket

e.g TCP

服务器端代码(字节)

客户端代码(字节 )

服务器端代码(字符)

客户端端代码(字符) 

UDP发送端

UDP接收端

服务器端发送音乐文件

客户端接收音乐文件 

IP

TCP/IP协议

数据的组织形式就是协议

netStat 指令  :查看网络状况

TCP和UDP协议

UDP(了解即可)

Socket

e.g TCP

服务器端代码(字节)

package e.gSocket;

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

/**
 * @auther xcz
 * @data 2024/4/26
 * @project e.gSocket
 * 服务器端
 */
public class socketServer {
    public static void main(String[] args) throws IOException {
        //思路
        //1、在本机的 9999 端口监听,等待连接
        //细节 : 要求本机没有其他服务监听 9999 端口
        //细节 : 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() 读取
        //   客户端写入数据通道中的数据,显示
        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));//根据读取到的实际长度显示内容
        }
        //获取 socket 关联的输出流
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("hello, client!".getBytes());
        //设置结束标记
        socket.shutdownOutput();

        //关闭流与 socket
        inputStream.close();
        socket.close();
        serverSocket.close(); //关闭
        outputStream.close();
    }
}

客户端代码(字节 )

package e.gSocket;

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

/**
 * @auther xcz
 * @data 2024/4/26
 * @project e.gSocket
 * 客户端 , 发送 “ hello,server” 给服务器端
 */
public class socketPC {
    public static void main(String[] args) throws IOException {
        //思路
        //1、连接服务器(ip,端口)
        //连接本机的 9999 端口, 如果链接成功,则会返回一个 Socket 对象
        Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
        System.out.println("客户端 Socket = " + socket );

        //2、连接上后,生成Socket 对象,通过socket.getOutputStream()得到和
        //socket 对象关联的输出流对象
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("hello,server".getBytes());
        //设置 结束标记
        socket.shutdownOutput();
        //获取 socket 关联的输入流,读取数据(字节),并显示
        //4、IO读取
        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));//根据读取到的实际长度显示内容
        }
        //关闭流与相关资源,必须关闭
        inputStream.close();
        outputStream.close();
        socket.close();
        System.out.println("Socket与outputStream 已关闭,客户端退出!");
    }
}

服务器端代码(字符)

package e.gSocket;

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

/**
 * @auther xcz
 * @data 2024/4/26
 * @project e.gSocket
 * 使用字符流
 */
public class socketServer01 {
    public static void main(String[] args) throws IOException {
        //思路
        //1、在本机的 9999 端口监听,等待连接
        //细节 : 要求本机没有其他服务监听 9999 端口
        //细节 : 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() 读取
        //   客户端写入数据通道中的数据,显示
        InputStream inputStream = socket.getInputStream();

        //4、IO读取
        //使用 转换流 InputStreamReader 将字节流转化会字符流
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String s = bufferedReader.readLine();
        System.out.println("来自PC端内容:" + s);
        //获取 socket 关联的输出流
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        bufferedWriter.write("hello, client,i am king!");
        bufferedWriter.newLine();  // 结束标记
        bufferedWriter.flush();  //刷新


        //关闭流与 socket
        inputStream.close();
        socket.close();
        serverSocket.close(); //关闭
        bufferedReader.close();
        bufferedWriter.close();
    }
}

客户端端代码(字符) 

package e.gSocket;

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

/**
 * @auther xcz
 * @data 2024/4/26
 * @project e.gSocket
 * 使用字符流
 */
public class socketPC01 {
        public static void main(String[] args) throws IOException {
            //思路
            //1、连接服务器(ip,端口)
            //连接本机的 9999 端口, 如果链接成功,则会返回一个 Socket 对象
            Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
            System.out.println("客户端 Socket = " + socket );

            //2、连接上后,生成Socket 对象,使用字符流
            BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            bufferedWriter.write("hello, server! 字符流");
            //结束标记
            bufferedWriter.newLine(); //插入换行,表示写入的内容结束,注意: 要求对方也必须用 readLine() 来读取!!
            bufferedWriter.flush();   //使用字符流需要手动刷新,否则不会写入数据通道

            //获取 socket 关联的输入流,读取数据(字节),并显示
            //4、IO读取
            //使用 转换流 InputStreamReader 将字节流转化会字符流
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String s = bufferedReader.readLine();
            System.out.println("来自服务器端内容:" + s);

            //关闭流与相关资源,必须关闭
            bufferedReader.close();
            bufferedWriter.close();
            socket.close();
            System.out.println("Socket与outputStream 已关闭,客户端退出!");
        }
    }

UDP发送端

package eg.gUDP;

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

/**
 * @auther xcz
 * @data 2024/4/26
 * @project eg.gUDP
 * UDP 发送端
 */
public class uDPSender {
    public static void main(String[] args) throws IOException {
        //   =====发送消息=====
        // 创建一个 DatagramSocket 对象,准备在 9999 端口接收数据也可以发送数据
        DatagramSocket datagramSocket = new DatagramSocket(9998);

        //将要发送的数据 封装到一个 DatagramPacket 对象
        byte[] data = "hello,明天出来嗨皮吗?".getBytes();
        //说明:封装的对象 DatagramPacket (对象 data 内容字节数组 ,data.length, 主机IP, 端口)
        DatagramPacket datagramPacket =
                new DatagramPacket(data, data.length, InetAddress.getByName("192.168.128.1"),9999);
        datagramSocket.send(datagramPacket);

        //关闭资源
        datagramSocket.close();
        System.out.println("数据发送完毕!");
    }
}

UDP接收端

package eg.gUDP;

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


/**
 * @auther xcz
 * @data 2024/4/26
 * @project eg.gUDP
 * UDP接收端
 */
public class uDPReciver {
    public static void main(String[] args) throws IOException {
        // ==========接收消息============
        // 创建一个 DatagramSocket 对象,准备在 9999 端口接收数据或发送数据
        DatagramSocket datagramSocket = new DatagramSocket(9999);

//        构建一个 DatagramPacket 对象,准备接受数据
//           UDP 协议中,一个数据包/报 最大64k
        byte[] bytes = new byte[1024];
        DatagramPacket datagramPacket = new DatagramPacket(bytes,bytes.length);

        //调用接收方法, 将通过网络传输的 DatagramPacket 对象
        // 填充到 packet 对象
        // 当有数据包 发送到 本机端口 9999 端口时,就会接收到数据到
        // 如果没有数据包发送到 本机 9999 端口 ,就会阻塞等待
        System.out.println("接收端 正在等待接收数据~");
        datagramSocket.receive(datagramPacket);

        //可以把 packet 进行拆包,取出数据,并显示
        int length = datagramPacket.getLength();  //实际接收到的数据字节长度
        byte[] data = datagramPacket.getData();  //接收到数据
        String s = new String(data,0,length);
        System.out.println(s);

//        关闭资源
        datagramSocket.close();
        System.out.println("数据接受完毕!");
    }
}

服务器端发送音乐文件

package eg.downFile;

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

/**
 * @auther xcz
 * @data 2024/4/27
 * @project eg.downFile
 * 思路: 创建端口监听 -> 等待客户端连接 -> 收到客户端发送的文件名 -> 进行文件名判断 ->
 * -> 构造文件路径读取本地文件 -> 转化为数组 -> 得到Socket关联输出流 -> 发送给客户端 -> 关闭流
 * 服务器端
 */
public class server_ {
    public static void main(String[] args) throws Exception {

        //  在端口 9999 监听
        System.out.println("服务器端,在 9999 端口监听");
        ServerSocket serverSocket = new ServerSocket(9999);
        //  等待客户端连接
        Socket socket = serverSocket.accept();
        //  读取客户端发送的文件名
        InputStream inputStream = socket.getInputStream();
        byte[] bytes = new byte[1024];
        String downLoad = new String(bytes,0,inputStream.read(bytes));
        System.out.println("客户端希望下载的名称是:" + downLoad);
        //   如果客户端希望下载的是稻香则读取 稻香,否则读取 不将就
        String fielPath;
        if ("稻香".equals(downLoad)){
            fielPath = "e:\\音乐\\" + downLoad + ".mp3";  //"E:\音乐\稻香.mp3"
        }else {
            fielPath = "e:\\音乐\\不将就"+".mp3";  //"E:\音乐\不将就.mp3"
        }
        //  创建输入流 读取文件
        BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(fielPath));
        //  用工具类读取文件,得到字符数组
        byte[] data = streamToByteArray(bufferedInputStream);

        //  将得到的字符数组 发送给 客户端 ,创建 Socket 关联的输出流
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(socket.getOutputStream());
        bufferedOutputStream.write(data);
        socket.shutdownOutput();  //设置结束标记

        //关闭流
        socket.close();
        inputStream.close();
        bufferedOutputStream.close();
        serverSocket.close();
        System.out.println("文件发送完毕!服务端退出!");

    }
    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.close();
        return array;
    }
}

客户端接收音乐文件 

package eg.downFile;

import com.sun.xml.internal.ws.util.StreamUtils;

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

/**
 * @auther xcz
 * @data 2024/4/27
 * @project eg.downFile
 * 思路:接收键盘输入 -> 连接服务器端发送文件名 -> 接收服务器端发的文件 -> 用工具类转换为字符数组
 * -> 将数据写入到本地磁盘
 * 客户端
 */
public class PC_ {
    public static void main(String[] args) throws Exception {

        //接收用户输入 下载文件名
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入想下载的歌曲:");
        String fileName = scanner.next();

        //连接服务端准备发送
        Socket socket = new Socket(InetAddress.getLocalHost(), 9999);

        //获取与 socket 关联的输出流
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write(fileName.getBytes());
        socket.shutdownOutput();

        //接收 服务器端 发来的文件
        BufferedInputStream bufferedInputStream = new BufferedInputStream(socket.getInputStream());
        //使用工具类 来得到数据
        byte[] data = streamToByteArray(bufferedInputStream);

        //将文件下载到指定位置
        String filePath = "e:\\" + fileName + ".mp3";  //"E:\音乐\稻香.mp3"
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(filePath));
        bufferedOutputStream.write(data);

        //关闭相关资源
        socket.close();
        scanner.close();
        outputStream.close();
        bufferedOutputStream.close();
        bufferedInputStream.close();
        System.out.println("文件下载完毕!客户端退出!");
    }
    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.close();
        return array;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值