百色彭于晏 2022-07-29 01:16 采纳率: 100%
浏览 41
已结题

java TCP通信中服务器怎么区分客户端发来的文件类型?

问题遇到的现象和发生背景

我最近遇到一个问题,就是我学到TCP通信的时候,假如,我作为客户端发送文件给服务器的时候,如果这个文件是一个.jpg的照片,那么我就得在服务器的文件保存路径的末尾加上.jpg 。这样不就变成面向结果编程了嘛?因为我客服端发送的文件是随机格式的,那么服务端应该怎么区别并接收不同类型的文件呢?

问题相关代码,请勿粘贴截图

这是客户端的代码

import java.net.Socket;
import java.io.*;
//   (主线程负责发消息,子线程负责收消息)
public class Client{
    public static void main(String[] args) {
        try {
            System.out.println("====客户端启动===");
            Socket socket = new Socket("127.0.0.1", 9998);
            new ClientThread(socket).start();//新的线程 这个线程用于消息的接收


            //1.先将磁盘中的文件读到内存中来    (使用 字节输入流)
            InputStream f=new FileInputStream("E:\\Documets\\Desktop\\123.jpg");
            BufferedInputStream br=new BufferedInputStream(f);      //包装成字节缓存输入流  传送速度快

            //2.将内存中文件数据 发送到网络介质上   (使用字节输出流)
            OutputStream os = socket.getOutputStream();     //定义发送管道
            PrintStream ps = new PrintStream(os);           //包装成打印流 速度更快!!!

            byte[] buffer=new byte[8192];
            int len;
            while ((len = br.read(buffer)) != -1) {             //通过 缓存字节输入流 接收字节到 buffer中去 并记录数组中的长度len
                ps.write(buffer, 0, len);          //将buffer中的字节 通过打印流 发送到网络介质中去
            }
            ps.flush();
            socket.shutdownOutput();            //关闭io  而不关闭管道!
            System.out.println("文件发给服务器成功!");

            // 关闭资源。
            //socket.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}



这是 客户端 子线程的的代码

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

//这个线程类  作为 接收客户端读服务器发来的消息
public class ClientThread extends Thread {//线程类 要继承Thread 或者实现 Runnable 接口
    private  Socket  socket;              //用来存套接字
    public ClientThread (Socket socket){   //构造方法,用来接收  与服务器连接的管道对管道进行读操作
        this.socket = socket;
    }
    @Override
    public void run() {//重写run方法
        try {
            //1.定义 字节输入流 从网络介质中获取数据存入内存中
            InputStream is=socket.getInputStream();
            BufferedInputStream br=new BufferedInputStream(is);      //包装成字节缓存输入流  传送速度快

            //2. 定义 打印流将文件数据从内存中写入磁盘
            File file=new File("E:\\Documets\\Desktop\\客户\\服务器发来的.jpg");      //选择保存路径
            PrintStream ps = new PrintStream(file);
            byte[] buffer=new byte[8192];
            int len;
            while( (len= br.read(buffer))!=-1 ){
                ps.write(buffer,0,len);             //将文件写入上面的文件路径中去
            }
            ps.flush();
            System.out.println("接收来自服务器的文件成功!");
        } catch (Exception e) {
            System.out.println("与服务器断开连接!");
        }


    }
}



这是 服务器的代码

import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
//使用两个线程 主线程 用于将连接过来的套接字 添加到集合 代表当前在线的人数
public class Server {
    /*创建一个Socket的list集合 用来装套接字  Socket=(IP地址:端口号)   */
    public static final List<Socket> onLineSockets = new ArrayList<>();  //当客户端连接上服务器的时候,就将客户端的套接字存入集合中
    public static void main(String[] args) {
        try {
            System.out.println("===服务端启动成功===");
            // 1、注册端口
            ServerSocket serverSocket = new ServerSocket(9998);
            // a.定义一个死循环由主线程负责不断的接收客户端的Socket管道连接。
            while (true) {
                // 2、每接收到一个客户端的Socket管道,交给一个独立的子线程负责读取消息
                Socket socket = serverSocket.accept();
                System.out.println(socket.getRemoteSocketAddress()+ "上线了!");
                //这里可以加上日志框架 打印日志
                onLineSockets.add(socket);// 把当前客户端管道Socket加入到在线集合中去
                // 3、开始创建独立线程处理socket
                new ServerThread(socket).start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

这是服务器子线程的代码


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

//创建线程类 本类用于数据的发送
public class ServerThread  extends  Thread{
    private  Socket socket;

    public ServerThread  (Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() { //重写run方法
        try {
            //1. 定义字节输入流,用于将网络介质上的文件数据 输入到内存(接收来自某一客户的文件数据)
            InputStream is=socket.getInputStream();
            BufferedInputStream br=new BufferedInputStream(is);      //包装成字节缓存输入流  传送速度快

            //2. 定义 打印流将文件数据从内存中写入磁盘  (接收来自客户端的文件 先存到服务器的磁盘下面)
            File file=new File("E:\\Documets\\Desktop\\服务器\\客户端发来的123.jpg");      //服务器的保存路径
            PrintStream ps0 = new PrintStream(file);
            byte[] buffer=new byte[8192];
            int len;
            while((len= br.read(buffer))!=-1){
                ps0.write(buffer ,0 ,len);
                ps0.flush();
            }
            socket.shutdownInput();
            System.out.println("接收来自 "+socket.getRemoteSocketAddress()+ "的文件成功!\n");

            //将文件发给所有人
            sendFileToAll(file);

        } catch (IOException e) {
            e.printStackTrace();
        }

    }
    //将字符串进行发送
    private void sendFileToAll(File file) {
        try {
            //3.将服务器磁盘中的文件 输入到内存中来
            InputStream is=new FileInputStream(file);       //多态 子类对象 传给父类类型
            BufferedInputStream br=new BufferedInputStream(is);      //包装成字节缓存输入流  传送速度快

             //4.定义字节输出流 ,用于将内存中的文件 输出到网络上 (将文件发给别的客户)
           OutputStream os=socket.getOutputStream();
           PrintStream ps = new PrintStream(os);            //包装成打印流
           //BufferedOutputStream bos=new BufferedOutputStream(os);

            int len;
            byte[] buffer=new byte[8192];
           // for (Socket onLineSocket : Server.onLineSockets) {
                // 除了自己的socket,其他socket我都发!!
                if(true){
                    while ((len=br.read(buffer))!=-1) {            //通过 缓存字节输入流 接收字节到 buffer中去 并记录数组中的长度len
                      ps.write(buffer, 0 , len);          //将buffer中的字节 通过打印流 发送到网络介质中去
                    }
                }
          //  }
//            br.close();
//            ps.close();
            socket.shutdownOutput();
            System.out.println("发送给所有客户成功!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

真的不知道怎么解决 。
因为服务器不知道网络介质上的文件 是什么格式的 所以应该怎么接收呢?


运行结果及报错内容

img


然后现在的问题就是,第二步到第三步,服务器怎么知道网络上的数据是.jpg格式?

我的解答思路和尝试过的方法

是不是要先用正则表达式先截取小数点后面的格式类型,然后作为消息发过先 然后再进行字符串的拼接,再创建服务器的文件对象?

我想要达到的结果

我希望能达到的效果是 :客户端发送文件到服务器,然后服务器能区别文件格式并将他保存到服务器的磁盘下,然后再将磁盘的文件发回给客户端

  • 写回答

2条回答 默认 最新

  • sum墨 2022-07-29 07:44
    关注

    我觉得一个很简单的做法是,在客户端就识别出类型,传输的时候把文件类型一起带给你

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 8月7日
  • 已采纳回答 7月30日
  • 创建了问题 7月29日

悬赏问题

  • ¥20 Js代码报错问题不知道怎么解决
  • ¥15 gojs 点击按钮node的position位置进行改变,再次点击回到原来的位置
  • ¥15 计算决策面并仿真附上结果
  • ¥20 halcon 图像拼接
  • ¥15 webstorm上开发的vue3+vite5+typeScript打包时报错
  • ¥15 vue使用gojs,需求在link中的虚线上添加方向箭头
  • ¥15 CSS通配符清除内外边距为什么可以覆盖默认样式?
  • ¥15 SPSS分类模型实训题步骤
  • ¥100 求ASMedia ASM1184e & ASM1187e 芯片datasheet/规格书
  • ¥15 求解决扩散模型代码问题