Java网络多线程(TCP/UDP网络编程)【一】

TCP网络编程

Socket

套接字(?)

在这里插入图片描述

在这里插入图片描述

应用案例1(字节流)

在这里插入图片描述

在这里插入图片描述

服务端

package socket;

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

/**
 * @author 
 * @date 2024-04-22 11:01
 */

public class SocketTCP01Server {
    public static void main(String[] args) throws IOException {
        //监听9999端口
        //ServerSocket可通过accept()返回多个Socket[多个客户端连接高并发]
        ServerSocket serverSocket = new ServerSocket(9999);
        System.out.println("服务端-端口9999等待连接...");
        //没有客户端连接时,阻塞端口
        //连接成功返回socket对象
        Socket socket = serverSocket.accept();
        System.out.println("socket is " + socket.getClass());
        //通过输入流, 获取数据通道中写入的数据
        InputStream inputStream = socket.getInputStream();
        byte[] buf = new byte[1024];
        int readLen = 0;
        //inputStream.read(buf) 方法尝试从输入流中读取数据到 buf 数组中。
        // 它返回实际读取的字节数,如果已经到达流的末尾,则返回 -1。
        while ((readLen = inputStream.read(buf)) != -1) {
            System.out.println(new String(buf, 0,readLen));
        }
        inputStream.close();
        socket.close();
        serverSocket.close();
        System.out.println("服务端关闭...");
    }
}

服务端控制台输出

服务端-端口9999等待连接...
socket is class java.net.Socket
hello, server
服务端关闭...

客户端

package socket;

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

/**
 * @author
 * @date 2024-04-22 11:09
 * Client 发送"hello, server"
 */

public class SocketTCP01Client {
    public static void main(String[] args) throws IOException {
        //连接服务端(ip,port)
        Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
        System.out.println("socket is " + socket.getClass());
        //得到和socket对象得输出流对象
        OutputStream outputStream = socket.getOutputStream();
        //通过输出流,将数据写入数据通道
        outputStream.write("hello, server".getBytes());
        //关闭流和socket的对象,释放占用的资源
        outputStream.close();
        socket.close();
        System.out.println("客户端关闭...");
    }
}

客户端控制台输出

socket is class java.net.Socket
客户端关闭...

应用案例2(字节流)

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

需要设置结束标记

socket.shutdownOutput(); socket.shutdownInput();

服务端

package socket.example2;

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

/**
 * @author 
 * @date 2024-04-22 14:04
 */

public class SocketTCP02Server {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(9999);
        System.out.println("服务端-端口9999等待连接...");
        Socket socket = serverSocket.accept();
        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));
        }
        socket.shutdownInput();
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("hello, client".getBytes());
        socket.shutdownOutput();    //设置写入结束标记

        inputStream.close();
        outputStream.close();
        socket.close();
        serverSocket.close();
    }
}

控制台输出

服务端-端口9999等待连接...
hello, server

客户端

package socket.example2;

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

/**
 * @author 
 * @date 2024-04-22 14:04
 */
//@SuppressWarnings("all")
public class SocketTCP02Client {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket(InetAddress.getLocalHost(),9999);
        System.out.println("客户端socket已启动");
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("hello, server".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));
        }
        socket.shutdownInput();

        outputStream.close();
        inputStream.close();
        socket.close();
    }
}

控制台输出

客户端socket已启动
hello, client

应用案例3(字符流)

在这里插入图片描述

在这里插入图片描述

服务端

package socket.example3;

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

/**
 * @author 
 * @date 2024-04-22 14:43
 * 使用字符流
 */

public class SocketTCP03Server {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(9999);
        System.out.println("服务端-端口9999等待连接...");
        Socket socket = serverSocket.accept();
        InputStream inputStream = socket.getInputStream();

        //使用字符流,使用InputStreamReader 将inputStream字节流转成字符流
        BufferedReader bufferedReader = new BufferedReader(
                new InputStreamReader(inputStream)
        );
        String str = bufferedReader.readLine();
        System.out.println(str);
        OutputStream outputStream = socket.getOutputStream();

        //使用字符流写入数据通道
        //OutputStreamWriter是从字符流到字节流的桥接
        //1、字符的输出需要通过字符流来操作,但是本质最后还是通过字节流输出到计算机上进行存储的
        //2、 因此OutputStreamWriter流的作用就是利用字节流作为底层输出流然后构建字符输出流,
        // 字符输出流输出字符到流中,然后通过指定的字符集把流中的字符编码成字节输出到字节流中,
        // 其作用就是一个桥梁,使得双方链接起来
        BufferedWriter bufferedWriter = new BufferedWriter(
                new OutputStreamWriter(outputStream)
        );
        bufferedWriter.write("hello, client 字符流");
        bufferedWriter.newLine();   //插入一个换行符,表示写入的内容结束,要求对方使用readLine
        bufferedWriter.flush(); //使用flush将缓冲区中的内容写入

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

控制台输出

服务端-端口9999等待连接...
hello, server 字符流

客户端

package socket.example3;

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

/**
 * @author 
 * @date 2024-04-22 14:43
 * 使用字符流
 */

public class SocketTCP03Client {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket(InetAddress.getLocalHost(),9999);
        System.out.println("客户端socket已启动");
        OutputStream outputStream = socket.getOutputStream();

        BufferedWriter bufferedWriter = new BufferedWriter(
                new OutputStreamWriter(outputStream)
        );
        bufferedWriter.write("hello, server 字符流");
        bufferedWriter.newLine();
        bufferedWriter.flush();


        InputStream inputStream = socket.getInputStream();

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

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

控制台输出

客户端socket已启动
hello, client 字符流

应用案例4

在这里插入图片描述

在这里插入图片描述

服务端

package socket.example4;

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

/**
 * @author 
 * @date 2024-04-25 15:40
 * 文件上传的服务端
 */

public class SocketTCP04FileUploadServer {
    public static void main(String[] args) throws IOException {

        ServerSocket serverSocket = new ServerSocket(9999);
        System.out.println("服务端-端口9999等待连接...");
        Socket socket = serverSocket.accept();

        //读取客户端发送的数据
        BufferedInputStream bufferedInputStream = new BufferedInputStream(socket.getInputStream());
        byte[] bytes = StreamUtils.streamToByteArray(bufferedInputStream);
        //获取当前的工作目录
        String serverPath = System.setProperty("user.dir", "path/to/directory") + "\\0.jpeg";
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(serverPath));
        bufferedOutputStream.write(bytes);
        bufferedOutputStream.close();

        //向客户端发送 收到图片的消息然后退出
        BufferedWriter bufferedWriter = new BufferedWriter(
                new OutputStreamWriter(socket.getOutputStream())
        );
        bufferedWriter.write("收到图片");
        bufferedWriter.newLine();
        bufferedWriter.flush();
        socket.shutdownOutput();

        bufferedWriter.close();
        bufferedInputStream.close();
        socket.close();
        serverSocket.close();


    }
}

控制台输出

服务端-端口9999等待连接...

客户端

package socket.example4;

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

/**
 * @author 
 * @date 2024-04-25 15:39
 * 文件上传的客户端
 */

public class SocketTCP04FileUploadClient {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket(InetAddress.getLocalHost(),9999);
        System.out.println("客户端socket已启动");

        String filePath = "E:\\0.jpeg";
        //创建读取磁盘文件的输入流
        BufferedInputStream bufferedInputStream = new BufferedInputStream(
                new FileInputStream(filePath)
        );
        //bytes为filePath文件对应字节数组
        byte[] bytes = StreamUtils.streamToByteArray(bufferedInputStream);

        //通过socket获取到输出流,将bytes数据发送给服务器
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(
                socket.getOutputStream()
        );
        bufferedOutputStream.write(bytes);  //将文件对应的字节数组的内容,写入到数据通道中
        socket.shutdownOutput();

        BufferedReader bufferedReader = new BufferedReader(
                new InputStreamReader(socket.getInputStream())
        );
        String str = bufferedReader.readLine();
        System.out.println("客户端接收到消息:" + str);
        bufferedReader.close();

        bufferedInputStream.close();
        bufferedOutputStream.close();
        socket.close();
    }
}

控制台输出

客户端socket已启动
客户端接收到消息:收到图片

netstat指令

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

2.netstat -an | more 分页显示

3.netstat -anb 可以查看到哪个程序在监听

TCP连接

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

UDP网络编程

DatagramSocket和DatagramPacket

在这里插入图片描述

在这里插入图片描述

应用案例

在这里插入图片描述

A端

package UDPProgramming.example01;

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

/**
 * @author 
 * @date 2024-04-25 22:18
 * UDP接收端
 */

public class UDPReceiverA {
    public static void main(String[] args) throws IOException {
        //创建一个datagramSocket对象在端口9999
        DatagramSocket datagramSocket = new DatagramSocket(9999);
        //构建datagramPacket对象用于接收数据
        byte[] buffer = new byte[64 * 1024];    //UDP一个数据包最大64K
        DatagramPacket datagramPacket = new DatagramPacket(buffer, buffer.length);
        //通过网络传输的 datagramPacket 接收数据
        System.out.println("等待接收数据中...");
        datagramSocket.receive(datagramPacket); //没有接收到数据包会阻塞

        //可以把 datagramPacket 进行拆包,取出里面的内容
        int length = datagramPacket.getLength();
        byte[] data = datagramPacket.getData();
        System.out.println("A端收到消息--"+new String(data, 0, length));

        byte[] sendData = "好的,明天见".getBytes();
        datagramPacket = new DatagramPacket(sendData, sendData.length,
                InetAddress.getByName("192.168.123.86"), 9998);
        datagramSocket.send(datagramPacket);
        System.out.println("发送完成");

        //释放资源
        datagramSocket.close();
        System.out.println("A端关闭");
    }
}

控制台输出

等待接收数据中...
A端收到消息--hello, 明天吃火锅~
发送完成
A端关闭

B端

package UDPProgramming.example01;

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

/**
 * @author
 * @date 2024-04-25 22:19
 * UDP发送端
 */

public class UDPReceiverB {
    public static void main(String[] args) throws IOException {
        DatagramSocket datagramSocket = new DatagramSocket(9998);
        byte[] data = "hello, 明天吃火锅~".getBytes();
        /*
        * data -> 内容
        * data.length -> 内容长度
        * InetAddress.getByName("192.168.123.86") -> 主机地址
        * 9999 -> 端口
        */
        DatagramPacket datagramPacket = new DatagramPacket(
                data,
                data.length,
                InetAddress.getByName("192.168.123.86"),
                9999);
        datagramSocket.send(datagramPacket);
        System.out.println("发送完成");

        datagramSocket.receive(datagramPacket);
        int length = datagramPacket.getLength();
        byte[] receiveData = datagramPacket.getData();
        System.out.println("B端收到消息--" + new String(receiveData, 0, length));

        //关闭资源
        datagramSocket.close();
        System.out.println("B端关闭");
    }
}

控制台输出

发送完成
B端收到消息--好的,明天见
B端关闭
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值