Java Socket远程传递录音

Java Socket远程传递录音

-摘要
最近写基于Java CS的远程监控的程序,我想实现的功能有,远程控制电脑屏幕,并可以实现关机,重启,捕捉音频,文件上传下载,并实时远程获取键盘,鼠标的监听事件,目前还有远程鼠标键盘的交互没有完成,后面会继续研究


-学习感悟
写一个完整的远程监控系统,对于刚入门Socket的人来说,十分困难,但逐个分解功能,最后再一个个把功能点结合起来,就是一个完整的系统.这样,入手很简单,尽管结合时会发现也有点困难,但整合的过程中,你会发现问题,也会提高自己对Socketde的理解


注:
-以上只是我的个人学习经验,不喜勿喷,谢谢!
-以下,直接贴代码,代码实现了服务端录音,并实时录音传给客户端


客户端(负责实时播放录音)

package test.audio;

import javax.sound.sampled.*;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.Socket;

/**
 * Created by zqq3436 on 2017/3/22.
 */
public class Client extends Thread {
    private ByteArrayInputStream bins;
    private Socket socket;
    private ObjectOutputStream out;
    private DataInputStream dins;
    private AudioInputStream audioInputStream;
    private SourceDataLine sourceDataLine;
    //初始化socket
    public Client() {
        try {
            socket = new Socket("localhost", 9090);//localhost可修改为连接服务端的IP地址
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //入口方法,开启播放线程
    public static void main(String[] args) {
        Client c = new Client();
        c.start();

    }
//播放线程
    public void run() {
        int Len = 0;
        try {
        //初始化输入输出流
            dins = new DataInputStream(socket.getInputStream());
            out = new ObjectOutputStream(socket.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
        //循环读取录音,并播放
            while (true) {
        //读取字节数组长度
                Len = dins.readInt();
                //读取字节数组
                byte[] iData = new byte[Len];
                dins.readFully(iData);
                 //将字节数组放到字节数组输入流
                bins = new ByteArrayInputStream(iData);
                //取得录音数据的输入流
                AudioFormat audioFormat = getAudioFormat();
                audioInputStream = new AudioInputStream(bins,
                        audioFormat, Len / audioFormat.getFrameSize());
                //构造音频输入流
                DataLine.Info dataLineInfo = new DataLine.Info(

                        SourceDataLine.class, audioFormat);

                sourceDataLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
                //打开具有指定格式的行,这样可使行获得所有所需的系统资源并变得可操作
                sourceDataLine.open(audioFormat);
                sourceDataLine.start();

                //定义临时缓冲区数组
                byte tempBuffer[] = new byte[Len];

                //读取数据到缓存数据
                int cnt = audioInputStream.read(tempBuffer, 0,

                        tempBuffer.length);

                if (cnt > 0) {


                    //通过此源数据行将音频数据写入混频器 (播放声音)
                    sourceDataLine.write(tempBuffer, 0, cnt);

                }

            }

        } catch (Exception e) {

            e.printStackTrace();

            System.exit(0);

        }


    }


    //取得AudioFormat
    private AudioFormat getAudioFormat() {

        //8000,11025,16000,22050,44100具有此格式的声音每秒播放或录制的样本数
        float sampleRate = 16000.0F;

        //8,16 每个具有此格式的声音样本中的位数
        int sampleSizeInBits = 16;

        //1,2使用此格式的音频信道数(单声道为 1,立体声为 2)。
        int channels = 1;


        //true,false可变比特率
        boolean signed = true;


        //true,false指示是以 big-endian 顺序还是 little-endian 顺序存储音频数据
        boolean bigEndian = false;


        return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed,

                bigEndian);

    }
}

服务端(负责实时录音,并传送给客户端)

 package test.audio;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.TargetDataLine;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * Created by zqq3436 on 2017/3/22.
 */
public class Server extends Thread {
    private ServerSocket server;
    private Socket socket;
    private DataOutputStream out;//输出流
    private AudioFormat audioFormat;
    private TargetDataLine targetDataLine;
    private ByteArrayOutputStream byteArrayOutputStream;
    private int totaldatasize;

    public Server() {
        //初始化ServerSocket,开启录音线程并传送给socket
        try {
            server = new ServerSocket(9090);
            System.out.println("wait.........");
            //等待socket接入
            socket = server.accept();
            System.out.println("socket:" + socket);
            out = new DataOutputStream(socket.getOutputStream());
//            开始录音,并传送给socket
            capture();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
//入口方法
    public static void main(String[] args) {
        new Server();
    }

    //取得AudioFormat
    private AudioFormat getAudioFormat() {

        //8000,11025,16000,22050,44100具有此格式的声音每秒播放或录制的样本数
        float sampleRate = 16000.0F;

        //8,16 每个具有此格式的声音样本中的位数
        int sampleSizeInBits = 16;

        //1,2使用此格式的音频信道数(单声道为 1,立体声为 2)。
        int channels = 1;

        //true,false可变比特率
        boolean signed = true;

        //true,false指示是以 big-endian 顺序还是 little-endian 顺序存储音频数据
        boolean bigEndian = false;

        return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed, bigEndian);

    }

    //录音
    private void capture() {

        try {

            //打开录音
            audioFormat = getAudioFormat();
            //构造数据行的信息对象
            DataLine.Info dataLineInfo = new DataLine.Info(
                    TargetDataLine.class, audioFormat);
            targetDataLine = (TargetDataLine) AudioSystem.getLine(dataLineInfo); 
            //打开具有指定格式的行,这样可使行获得所有所需的系统资源并变得可操作
            targetDataLine.open(audioFormat); 
            //创建独立线程进行录音
            targetDataLine.start();
            Thread captureThread = new Thread(new Server.CaptureThread());
            captureThread.start();

        } catch (Exception e) {

            e.printStackTrace();


        }

    }

    //录音线程
    class CaptureThread extends Thread {
        //创建临时缓冲数组
        byte tempBuffer[] = new byte[10000];
        public void run() {

            try {
               //循环录音
                while (true) {
                //不断创建字节数组输出流
                    byteArrayOutputStream = new ByteArrayOutputStream();
                    //读取10000个数据
                    int cnt = targetDataLine.read(tempBuffer, 0,

                            tempBuffer.length);
                    byte[] b;
                    if (cnt > 0) {
                        //保存该录音数据
                        byteArrayOutputStream.write(tempBuffer, 0, cnt);
                        b = byteArrayOutputStream.toByteArray();

                        int length = b.length;
                        //输出字节数组长度
                        out.writeInt(length);
                        //输出字节数组
                        out.write(b);
                        //关闭字节数组输出流
                        byteArrayOutputStream.close();
                        Thread.sleep(100);//线程休眠
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }

    }

}

尾注:
-此代码对网上代码有参考,若对AudioFormat 相关内容不明白,建议参考Java Sound用法,谢谢!

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值