java-网络通信相关

Posted 小丑quan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java-网络通信相关相关的知识,希望对你有一定的参考价值。

 

 

 

java中 

 

 

 

Socket类

 

 

 

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

public class Client {
    public static void main(String[] args) throws IOException {
        //创建socket,指定服务器的ip 和端口
        Socket socket = new Socket("127.0.0.1",8888);
        //从socket里面获取字节输出流,准备给服务器发送数据
        OutputStream ops = socket.getOutputStream();
        ops.write("你好,全植强的服务器".getBytes());
//没有服务器会抛出异常:thread "main" java.net.ConnectException: Connection refused: connect
        //获取字节输入流,接受来自服务器的回馈数据
        InputStream ips =socket.getInputStream();

        byte[] bytes = new byte[1024];//创建接受字节数组,数组长度初定为
        int len = ips.read(bytes);//将数据读入数组,返回数组的长度
        System.out.println(new String(bytes,0,len));//输出数据

        socket.close();
    }
}

 

 

ServerSocket类

 

 

 

 

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

public class Server {
    public static void main(String[] args) throws IOException {
        //创建ServerSocket 指定端口号,不指定就有系统随机安排!!
        ServerSocket server = new ServerSocket(8888);
        //监听获取客户端的socket
        Socket socket= server.accept();
        //从获取到客户端的socket创建字节输入流,准备读取客户端发来的数据
        InputStream ips =socket.getInputStream();

        byte[] bytes = new byte[1024];
        int len = ips.read(bytes);//将数据读入数组,返回数据的长度
        System.out.println(new String(bytes,0,len));

        OutputStream ops = socket.getOutputStream();
        ops.write("收到小弟".getBytes());
        socket.close();
        server.close();
    }
}

 

 

TCP文件上传是咧

 

 

 

FileClient

 

 

 

/*
文件上传的客服端,读取本地文件,上传到服务器,读取服务器回写的数据
    数据源:Snipaste_2020-06-25_23-37-15.png
    目的地:服务器
 */
public class TcpSocketFileClient {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("Snipaste_2020-06-25_23-37-15.png");
        Socket socket = new Socket("127.0.0.1",8888);
        OutputStream os = socket.getOutputStream();
        int len = 0;
        byte[] bytes = new byte[1024];
        /*
        @return     the total number of bytes read into the buffer, or
     *             <code>-1</code> if there is no more data because the end of
     *             the file has been reached.
         */
        while ((len = fis.read(bytes)) != -1){
            System.out.println(len);
            os.write(bytes,0,len);
        }

        InputStream ips =socket.getInputStream();
        while ((len = ips.read(bytes)) != -1){
            System.out.println(new String(bytes,0,len));
        }

        fis.close();
        socket.close();
    }
}

 

 

FileServer::

 

 

 

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

public class TcpSocketFileServer {
    public static void main(String[] args) throws IOException {
        //创建服务器socket指定端口号
        ServerSocket server = new ServerSocket(8888);
        //监听客户端,获取socket
        Socket socket = server.accept();
        //获取socket中的字节输入流,读取客户端传进来的数据
        InputStream ips = socket.getInputStream();
        //判断文件对象是否存在
        File file = new File("d:\\\\upload");
        if(!file.exists()){
            file.mkdir();
        }
        //获取本地文件输出字节流,准备将从客户端获取到的文件写出到本地磁盘中
        FileOutputStream fops = new FileOutputStream(file+"\\\\up.png");
        //读取客户端发来的输入字节流
        int len = 0;
        byte[] bytes = new byte[1024];
        while ((len = ips.read(bytes))!= -1){
            //网本地输出字节流写入客户端的数据
            fops.write(bytes,0,len);
        }
        //使用socket中的字节输出字节流往客户端输出数据
        socket.getOutputStream().write("done".getBytes());
        fops.close();
        socket.close();
        server.close();

    }
}

运行服务器再运行客户端最后发现:

 

 

 

 

当时两个程序都没有停止下来,为什么:

 

 

 

解决方法;

 

 

 

客户端加入:

 

 

 结果,两个程序都结束,client也收到结果:

 

 

 

 

优化服务端

  /*
        优化,自定义一个文件的命名规则,防止同盟的文件被覆盖掉
            规则:域名+毫秒数+随机数

         */
        String filename = "\\\\better.quan"+System.currentTimeMillis()+new Random().nextInt(787878)+".png";
        FileOutputStream fops = new FileOutputStream(file+filename);
        //读取客户端发来的输入字节流
        int len = 0;
        byte[] bytes = new byte[1024];
        while ((len = ips.read(bytes))!= -1){
            //网本地输出字节流写入客户端的数据
            fops.write(bytes,0,len);
        }

结果:

 

 

 

优化2:让服务器不停下,持续监听,客户端就能不断上传文件:

   /*
        让服务器一直处于监听状态(死循环accept方法)
        有一个客户端上传文件,就保存一个文件
         */

        while (true){
            Socket socket = server.accept();
            //获取socket中的字节输入流,读取客户端传进来的数据
            InputStream ips = socket.getInputStream();
            //判断文件对象是否存在
            File file = new File("d:\\\\upload");
            if(!file.exists()){
                file.mkdir();
            }
            //获取本地文件输出字节流,准备将从客户端获取到的文件写出到本地磁盘中

        /*
        优化,自定义一个文件的命名规则,防止同盟的文件被覆盖掉
            规则:域名+毫秒数+随机数

         */
            String filename = "\\\\better.quan"+System.currentTimeMillis()+new Random().nextInt(787878)+".png";
            FileOutputStream fops = new FileOutputStream(file+filename);
            //读取客户端发来的输入字节流
            int len = 0;
            byte[] bytes = new byte[1024];
            while ((len = ips.read(bytes))!= -1){
                //网本地输出字节流写入客户端的数据
                fops.write(bytes,0,len);
            }
            //使用socket中的字节输出字节流往客户端输出数据
            socket.getOutputStream().write("done".getBytes());
            fops.close();
            socket.close();
        }
       //不用关闭服务器
//        server.close();

 

多次启动客户端

 

 

 

 

优化三:提高效率,利用多线程

来一个客户端上传文件请求,开启一个线程去处理

public class TcpSocketFileServer {
    public static void main(String[] args) throws IOException {
        //创建服务器socket指定端口号
        ServerSocket server = new ServerSocket(8888);
        //监听客户端,获取socket
        /*
        让服务器一直处于监听状态(死循环accept方法)
        有一个客户端上传文件,就保存一个文件
         */
        while (true) {
            Socket socket = server.accept();
            //获取socket中的字节输入流,读取客户端传进来的数据
            /*
            使用多线程,提高程序的效率
                有一个客户端上传文件,就开启一个线程,完成文件的上传
             */
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {//由于接口类当中没有throw异常,使用try catch
                        InputStream ips = socket.getInputStream();
                        //判断文件对象是否存在
                        File file = new File("d:\\\\upload");
                        if (!file.exists()) {
                            file.mkdir();
                        }
                        //获取本地文件输出字节流,准备将从客户端获取到的文件写出到本地磁盘中
                        /*
                        优化,自定义一个文件的命名规则,防止同盟的文件被覆盖掉
                            规则:域名+毫秒数+随机数
                         */
                        String filename = "\\\\better.quan" + System.currentTimeMillis() + new Random().nextInt(787878) + ".png";
                        FileOutputStream fops = new FileOutputStream(file + filename);
                        //读取客户端发来的输入字节流
                        int len = 0;
                        byte[] bytes = new byte[1024];
                        while ((len = ips.read(bytes)) != -1) {
                            //网本地输出字节流写入客户端的数据
                            fops.write(bytes, 0, len);
                        }
                        //使用socket中的字节输出字节流往客户端输出数据
                        socket.getOutputStream().write("done".getBytes());
                        fops.close();
                        socket.close();
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
            //不用关闭服务器
//        server.close();
        }
    }
}

 

 

模拟B\\S服务器

//BS服务器版本TCP服务器
public class BsTcpServer {
    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(8080);
        Socket socket = server.accept();

        InputStream ips = socket.getInputStream();
        byte[] bytes = new byte[1024];
        int len = 0;
        while ((len = ips.read(bytes))!= -1){
            System.out.println(new String(bytes,0,len));
        }
    }
}

运行并访问

 

 

 服务器输出为:

GET /testCOM.html HTTP/1.1   //地址请求的资源位置
Host: localhost:8080
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36 Edg/83.0.478.54
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Cookie: goSessionid=xf82SLPFkJGHj5qZcl_lsO6XFT-FTHwjgVlxkkQdzWs%3D

 

GET /testCOM.html HTTP/1.1 可以使用BufferReader的方法readline读取一行
new BufferedReader(new InputStreamReader(is)) 将网络字节输入流转换为字符缓冲输入流

再使用String 类方法split(" ") 切割字符串,获取中间的部分
再使用String的方法substring(1)获取html文件的路径
testCOM.html

  然后服务器建立一个本地字节输入流,根据获取到的文件路径读取html文件

  服务器使用网络字节输出流把读取到的文件写道客户端即浏览器显示

固定的浏览器写入:

//写入HTTP协议响应投,固定写法
out.write("HTTP/1.1 200 OK\\r\\n".getBytes());
out.write("Content-Type:text/html\\r\\n".getBytes());

//必须写入空行
out.write("\\r\\n".getBytes());

 

Server辰戌:

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

//BS服务器版本TCP服务器
public class BsTcpServer {
    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(8080);
        Socket socket = server.accept();

        InputStream ips = socket.getInputStream();
//        byte[] bytes = new byte[1024];
//        int len = 0;
//        while ((len = ips.read(bytes))!= -1){
//            System.out.println(new String(bytes,0,len));
//        }
        BufferedReader br =new BufferedReader(new InputStreamReader(ips));
        String line = br.readLine();//GET /resources/testCOM.html HTTP/1.1
        String[] strings = line.split(" ");// /resources/testCOM.html
        String htmlpath = strings[1].substring(1);//  resources/testCOM.html

        FileInputStream fips = new FileInputStream(htmlpath); //  resources/testCOM.html

        OutputStream ops =socket.getOutputStream();

        //写入HTTP协议响应投,固定写法
        ops.write("HTTP/1.1 200 OK\\r\\n".getBytes());
        ops.write("Content-Type:text/html\\r\\n".getBytes());
        //必须写入空行
        ops.write("\\r\\n".getBytes());

        int len = 0;
        byte[] bytes = new  byte[1024];
        while ((len = fips.read(bytes)) != -1){
            ops.write(bytes,0,len);
        }
        fips.close();
        socket.close();
        server.close();

    }
}

 

 

 

结果:

 

 

 

 

以上是关于java-网络通信相关的主要内容,如果未能解决你的问题,请参考以下文章

VSCode自定义代码片段14——Vue的axios网络请求封装

VSCode自定义代码片段14——Vue的axios网络请求封装

Android App 安全的HTTPS 通信

使用实体框架迁移时 SQL Server 连接抛出异常 - 添加代码片段

片段内容未出现在手机上

片段通信问题(尝试调用虚方法)