how to pass audio between sockets in java - java

Im try to pass audio between sockets but it pass one time in client than clients stops working.
I think the way im writing and sending may be wrong please help me regarding this code
Following is my server code :
public void run(){
try{
SetInitialSettings();
int bufferSize = (int) format.getSampleRate() * (int) format.getFrameSize();
System.out.println("length :" +bufferSize);
out = new ByteArrayOutputStream();
readagain=true;
while(record){
int count=0;
for(int i=0;i<1000;i++)
{
if(buffer==null){
buffer = new byte[bufferSize];
}
count = line.read(buffer, 0, buffer.length);
if (count > 0) {
//out.write(buffer, 0, count);
//readagain=false;
for (int j=0;i<ser.clientReceiver.audioSender.size();j++){
ser.clientReceiver.audioSender.get(i).cliOut.write("Audio".getBytes());
ser.clientReceiver.audioSender.get(i).cliOut.write('\n');
ser.clientReceiver.audioSender.get(i).cliOut.flush();
ser.clientReceiver.audioSender.get(i).cliOut.write(buffer,0,count);
ser.clientReceiver.audioSender.get(i).cliOut.flush();
Thread.sleep(2000);
}
}
}
}
}
catch(Exception ex)
{
System.out.println(ex.getMessage());
}
}
and following is my client code :
public void run(){
try{
//audioReceiver = new TAudioReceiver(cli);
//audioReceiver.start();
while(true){
//Thread.sleep(1000);
System.out.println("reading token");
cmd= cli.BufferedReader().readLine();
System.out.println("token :" +cmd);
switch (cmd) {
case "Msg":
message = cli.BufferedReader().readLine();
cmd="None";
break;
case "File":
GetFile();
break;
case "Audio":
PlayAudio();
break;
}
}
//reading msgs here
}
catch(Exception ex)
{
//throw new InterruptedException(ex.getMessage());
}
}
this is the function need to run when "audio" msg received from server to client
public void PlayAudio()throws Exception{
try{
cli.ServerInputStream().read(buffer);
audio = buffer;
audioIn = new ByteArrayInputStream(audio);
AudioFormat f = new AudioFormat(8000, 8, 1,true, true);
ain= new AudioInputStream(audioIn,f, audio.length/f.getFrameSize());
DataLine.Info info = new DataLine.Info(SourceDataLine.class, f);
try (SourceDataLine line = (SourceDataLine)AudioSystem.getLine(info)) {
int bufferSize = (int) f.getSampleRate()* f.getFrameSize();
buffer= new byte[bufferSize];
int count;
while ((count = ain.read(buffer, 0, buffer.length)) != -1) {
if (count > 0) {
line.write(buffer, 0, count);
}
}
line.drain();
}
}
catch(Exception ex)
{
System.out.println("file" + ex.getMessage());
}
}

Your original code was better. You must write(buffer, 0, count), not write(buffer). Otherwise you are writing junk at the end of each buffer that wasn't read by the last read. Your second piece of code ignores the result of read().

Related

Java socket getting only NUL characters after writing byte array

I'm trying to send files in chunks from a client to server via byte arrays. I'm using ObjectInputStream. The write works and the filesize matches but when I open the file, I only get a blank textfile(which when opened in a IDE, shows NUL,NUL,NUL...).
Server code:
try(
FileOutputStream fileOut = new FileOutputStream(file);
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
){
byte[] arr = new byte[chunkSize];
try {
int len = 0;
long bytesRead = 0;
byte[] bytes = new byte[chunkSize];
int chunkNo = 1;
while(true)
{
len = in.read(bytes,0, chunkSize);
System.out.println();
if(len < 0)
break;
fileOut.write(arr, 0, len);
bytesRead += len;
out.writeObject(Server.CHUNK_ACKNOWLEDGE_MSG);
String ackReply = (String) in.readObject();
if(ackReply.equalsIgnoreCase((Server.UPLOAD_ACKNOWLEDGE_RECEIVE_TIMEOUT_MSG))){
if(Server.DEBUG)
System.out.println(fileName + " send timeout.");
deleteFile();
break;
}else if (ackReply.equalsIgnoreCase(Server.UPLOAD_COMPLETE_MSG)){
if(bytesRead != fileSize){
System.out.println(fileName + " File size mismatch");
deleteFile();
break;
}else{
System.out.println( fileName + " File written");
break;
}
}
}
}catch (IOException ioe){
if(Server.DEBUG)
ioe.printStackTrace();
}
Client code:
try(
FileInputStream fileInput = new FileInputStream(file);
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
){
byte[] arr = new byte[chunkSize];
try {
int len = 0;
int bytesRead = 0;
int chunkCount = 1;
while((len = fileInput.read(arr, 0, chunkSize)) != -1)
{
out.write(arr, 0, len);
out.flush();
bytesRead += len;
}
try {
System.out.println("wait ack");
socket.setSoTimeout(timeout);
String ack = (String) in.readObject();
System.out.println(ack);
if(bytesRead >= fileSize){
out.writeObject(Server.UPLOAD_COMPLETE_MSG);
System.out.println(Server.UPLOAD_COMPLETE_MSG);
break;
}else{
out.writeObject(Server.CHUNK_ACKNOWLEDGE_MSG);
}
}catch (SocketTimeoutException e){
out.writeObject(Server.UPLOAD_ACKNOWLEDGE_RECEIVE_TIMEOUT_MSG);
System.out.println(Server.UPLOAD_ACKNOWLEDGE_RECEIVE_TIMEOUT_MSG);
break;
}finally {
socket.setSoTimeout(0);
}
}
}
}catch (IOException ioe){
ioe.printStackTrace();
}
}catch (FileNotFoundException fnfe){
System.out.println("No such file: " + fileName);
}catch (Exception e){
e.printStackTrace();
}
finally {
try {
socket.close();
}catch (Exception ex){
ex.printStackTrace();
}
}
I tried writing the byte array to another file on the client side and the copy was identical. So the problem must be during sending data over socket.
The Server.X_MSG is just a constant string. I don't know if mixing readobject() and read(bytearray) on the same ObjectInputStream causes any issues though.
Maybe it's because fileOut.write(arr, 0, len); use arr and len = in.read(bytes,0, chunkSize); use bytes? They are not the same array.

Turning byte array into Bitmap

I have a server in cpp and a client in Java where I am sending an image from the server to the client in segments. On the client side I pick up all the segment to form a single array of bytes.
My problem is that I don't seem to be able to successfully create a bitmap out of this byte array, since I get null using BitmapFactory.decodeByteArray()
Client code:
byte[] response_bytes;
private Bitmap receive_image ( final String protocol, final int image_size, final int buffer_size)
{
if (image_size <= 0 || buffer_size <= 0)
return null;
Thread image_receiver = new Thread(new Runnable() {
#Override
public void run() {
ByteBuffer byteBuffer = ByteBuffer.allocate(image_size);
byte[] buffer = new byte[buffer_size];
int bytesReadSum = 0;
try {
while (bytesReadSum != image_size) {
activeReader.read(buffer);
String message = new String(buffer);
if (TextUtils.substring(message, 0, len_of_protocol_number).equals(protocol)) {
int bytesToRead = Integer.parseInt(TextUtils.substring(message,
len_of_protocol_number,
len_of_protocol_number + len_of_data_len));
byteBuffer.put(Arrays.copyOfRange(buffer,
len_of_protocol_number + len_of_data_len,
bytesToRead + len_of_protocol_number + len_of_data_len));
bytesReadSum += bytesToRead;
} else {
response_bytes = null;
break;
}
}
if (bytesReadSum == image_size) {
byte[] image_bytes = byteBuffer.array();
if (image_bytes.length > 0)
response_bytes = image_bytes;
else
response_bytes = null;
}
} catch (IOException e) {
response_bytes = null;
}
}
});
image_receiver.start();
try {
image_receiver.join();
} catch (InterruptedException e) {
response_bytes = null;
}
if (response_bytes != null) { //Here image_bitmap is null
Bitmap image_bitmap = BitmapFactory.decodeByteArray(response_bytes, 0, response_bytes.length);
return image_bitmap;
} else {
return null;
}
At this point I'd also like to mention that the image bytes reading seems to work fine and I manage to read all the bytes of the image without fail.
Yet, I'm unable to turn that array of bytes into a bitmap.

Handling binary packets

I coded this packet handler but I can imagine scenarios in which it will get stuck or won't be able to read incomplete data. My questions are:
Should I use two buffers, one for the current incoming data and other to append incomplete data to?
I'm being stupidly over-complicated?
Code:
byte[] buffer;
int bufferLength;
int bytesRead;
buffer = new byte[1024];
while (bluetoothConnected) {
try {
// Wait for packet header
if (mmInStream.available() >= 8) {
bufferLength = mmInStream.read(buffer);
bytesRead = 0;
// Parse every packet
while (true) {
int commandType = ByteBuffer.wrap(buffer, 0, 2).order(ByteOrder.LITTLE_ENDIAN).getShort();
int payloadSize = ByteBuffer.wrap(buffer, 2, 2).order(ByteOrder.LITTLE_ENDIAN).getShort();
int packetSize = PACKET_HEADER_SIZE + payloadSize;
// Break if payload is incomplete
if (bufferLength < (bytesRead + packetSize)) {
// Append to other buffer
break;
}
byte[] packet = new byte[packetSize];
System.arraycopy(buffer, bytesRead, packet, 0, packetSize);
parsePacketSequence(socket, packet);
bytesRead += packetSize;
// Break if all bytes are read
if (bufferLength == bytesRead)
{
break;
}
// Break if more bytes are needed
// Packet header incomplete
if ((bufferLength - bytesRead) < PACKET_HEADER_SIZE)
{
// Append to other buffer
break;
}
}
}
}
catch (IOException e) {
bluetoothConnected = false;
Log.d(TAG, "Error " + e);
break;
}
}
Should I use two buffers, one for the current incoming data and other to append incomplete data to?
No.
I'm being stupidly over-complicated?
Yes.
Here's a simple version using DataInputStream:
DataInputStream din = new DataInputStream(mmInStream);
while (bluetoothConnected) {
try {
// Read packet header
int commandType = swap(din.readShort());
int payloadSize = swap(din.readShort());
int packetSize = PACKET_HEADER_SIZE + payloadSize;
byte[] packet = new byte[packetSize];
din.readFully(packet);
parsePacketSequence(socket, packet);
}
catch (IOException e) {
bluetoothConnected = false;
Log.d(TAG, "Error " + e);
break;
}
}
The swap() method which converts a short in litte-endian byte order to Java byte order is left as an exercise for the reader.
NB I don't see how parsePacketSequence() can work if it doesn't know commandType.
E&OE

Reading bytes from inputstream through serial port in java

I have a stream of bytes to be sent through a serial port. When all the bytes are sent I should receive a stream of bytes again through the inputstream.
Output Byte Array
byte[] command={(byte) 0xAA,0x55,0x05,0x00,0x55,(byte) 0xAA};
Expected Response
**Serial command received
Admin Mode - IR Learn
In IR Learner Mode
Press IR Key...**
Actual Response
**Serial command received
Admin Mode - IR Learn
In IR e - IR**
InputStream
public void serialEvent(SerialPortEvent event) {
try {
Thread.sleep(100);
} catch (InterruptedException e2) {
e2.printStackTrace();
}
StringBuilder sb = new StringBuilder();
try {
int length = inputStream.available();
readBuffer = new byte[length];
Thread.sleep(110);
while (inputStream.available() > 0) {
int numBytes = inputStream.read(readBuffer);
for (byte b : readBuffer) {
sb.append(new String(new byte[]{b}));
}
}
System.out.println(sb.toString());
JOptionPane.showMessageDialog(contentPane, "Learned code : " + sb.toString(), "Code", JOptionPane.INFORMATION_MESSAGE);
} catch (IOException e4) {
e4.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
readBuffer = null;
}
OutputStream
for (int i = 0; i < command.length; i++) {
outputStream.write(command, 0, command.length);
outputStream.flush();
}
How can I get the value without the repetition and JOptionPane?
Please help
Get rid of all the sleeps.
You're adding junk to the StringBuffer. Change this:
while (inputStream.available() > 0)
{
int numBytes = inputStream.read(readBuffer);
for (byte b:readBuffer)
{
sb.append(new String(new byte[] {b}));
}
}
to this:
while (inputStream.available() > 0)
{
int numBytes = inputStream.read(readBuffer);
if (numBytes < 0)
break;
sb.append(new String(readBuffer, 0, numBytes));
}
On the output side, you're writing every command several times. Change this:
for(int i=0;i<command.length;i++)
{
outputStream.write(command,0,command.length);
outputStream.flush();
}
to this:
outputStream.write(command,0,command.length);
outputStream.flush();

Knowing How to Detect a Disconnection when Reading Socket Data (InputStream)

I have a thread that is constantly reading data from an InputStream. The InputStream data is coming from a Bluetooth socket. Previously, I wasn't using the if(mmInStream.available() > 0) around the InputStream read statement and when the bluetooth socket went away (someone turned off the device), the mmInStream.read would throw a IOException and then I could process my disconnection logic. What is the best way to determine when a disconnect has occurred?
First byte of 0xEE tells me its the leader of the data packet and the second tells me the length to read.
public void run() {
byte[] tempBuffer = new byte[1024];
byte[] buffer = null;
int byteRead=0;
long timeout=0;
long wait=100;
while (true) {
try {
timeout = System.currentTimeMillis() + wait;
if(mmInStream.available() > 0) {
while((mmInStream.available() > 0) && (tempBuffer[0] != (byte) 0xEE) && (System.currentTimeMillis() < timeout)){
byteRead = mmInStream.read(tempBuffer, 0, 1);
}
if(tempBuffer[0] == (byte) 0xEE){
timeout = System.currentTimeMillis() + wait;
while(byteRead<2 && (System.currentTimeMillis() < timeout)){
byteRead += mmInStream.read(tempBuffer, 1, 1);
}
}
timeout = System.currentTimeMillis() + wait;
while((byteRead<tempBuffer[1]) && (System.currentTimeMillis() < timeout)){
byteRead += mmInStream.read(tempBuffer, byteRead, tempBuffer[1]-byteRead);
}
}
if(byteRead > 0){
//do something with the bytes read in
}
}
catch (IOException e) {
bluetoothConnectionLost();
break;
}
}
}
You don't need all this malarkey with available(). Just set a read timeout with setSoTimeout, read, detect read returning -1, use the count returned by read if > 0 rather than assuming the buffer got filled, catch SocketTimeoutException to detect read timeouts, and catch IOException to detect other breakages.
After a look at the documentation, I think it's like this:
public void run() {
byte[] tempBuffer = new byte[1024];
int byteRead = 0;
while (true) {
try {
bytesRead = mmInStream.read(tempBuffer, 0, tempBuffer.length);
if (bytesRead < 0)
// End of stream.
break;
// Do something with the bytes read in. There are bytesRead bytes in tempBuffer.
} catch (IOException e) {
bluetoothConnectionLost();
break;
}
}
}
I think it's like this:
void fun(){
isOpen = true;
try{
InputStream stream = socket.getInputStream();
while(isOpen){
byte[] buf = new byte[8];
int pos = stream.read(buf);
if (pos < 0) {
throw new IOException();
}
//dosomething...
}
}catch(IOException e) {
isOpen = false;
}finally{
//do dispose here
}
}

Categories

Resources