Send multiple files using Java NIO SocketChannel - java

I have tried sending files using java NIO socket channels according to this guide. It works fine. I modified the method to send List of files. Basically, i loop through the files list and call send method already implemented in the above-mentioned guide. There was an error "Address already in use" so I commented the socket closing line in FileSender class. After that, there was no error in the code. Seems the program stuck in middle. How do I solve this problem? is there any better way to solve the problem?
Main.Java
public static void main(String[] args) throws IOException, InterruptedException{
RunningConfiguration.run();
List<File> files = new <File>ArrayList();
File a = new File("pics/city.jpg");
File b = new File("pics/desert.jpg");
File c = new File("pics/flower.jpg");
File d = new File("pics/night.jpg");
List<Node> nodes = RunningConfiguration.getNodeList();
ListIterator li = nodes.listIterator();
while(li.hasNext()){
Node node = (Node)li.next();
FileSender.send(node, files, "pics/received/");
}
}
FileSender.Java
public class FileSender {
private final InetSocketAddress fileSocketAddress;
private final File file;
public FileSender(InetAddress inetAddress, File file) throws IOException{
this.fileSocketAddress = new InetSocketAddress(inetAddress,RunningConfiguration.FILE_PORT);
this.file = file;
}
public static void send(InetSocketAddress inetSocketAddress, File file) throws IOException{
FileSender nioClient = new FileSender(inetSocketAddress.getAddress(),file);
SocketChannel socketChannel = nioClient.createChannel();
nioClient.sendFile(socketChannel);
}
public static void send(Node to, File file) throws IOException{
FileSender nioClient = new FileSender(to.getSocketAddress().getAddress(),file);
SocketChannel socketChannel = nioClient.createChannel();
nioClient.sendFile(socketChannel);
}
public static void send(Node to, File file,String filepath) throws IOException{
FileSender nioClient = new FileSender(to.getSocketAddress().getAddress(),file);
SocketChannel socketChannel = nioClient.createChannel();
nioClient.sendFile(socketChannel);
}
public static void send(Node to,List<File> files,String filepath) throws IOException{
ListIterator ltr = files.listIterator();
while(ltr.hasNext()){
File file = (File) ltr.next();
FileSender nioClient = new FileSender(to.getSocketAddress().getAddress(),file);
SocketChannel socketChannel = nioClient.createChannel();
nioClient.sendFile(socketChannel);
}
}
public SocketChannel createChannel() {
SocketChannel socketChannel = null;
try {
socketChannel = SocketChannel.open();
SocketAddress socketAddress = this.fileSocketAddress;
socketChannel.connect(socketAddress);
System.out.println("Connected..Now sending the file");
} catch (IOException e) {
e.printStackTrace();
}
return socketChannel;
}
public void sendFile(SocketChannel socketChannel) {
RandomAccessFile aFile = null;
try {
//File file = new File("data\\web.exe");
aFile = new RandomAccessFile(this.file, "r");
FileChannel inChannel = aFile.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (inChannel.read(buffer) > 0) {
buffer.flip();
socketChannel.write(buffer);
buffer.clear();
}
Thread.sleep(400);
System.out.println("End of file reached..");
socketChannel.close();
aFile.close();
} catch (FileNotFoundException e ) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
FileReceiver.java
private String fileName;
public FileReceiver(String fileName) {
this.fileName = fileName;
}
public static void receive(String fileName) {
FileReceiver nioServer = new FileReceiver(fileName);
SocketChannel socketChannel = nioServer.createServerSocketChannel();
nioServer.readFileFromSocket(socketChannel);
}
public FileReceiver() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
public SocketChannel createServerSocketChannel() {
ServerSocketChannel serverSocketChannel = null;
SocketChannel socketChannel = null;
try {
System.out.println("File receiver listening at port: " + RunningConfiguration.FILE_PORT);
serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(RunningConfiguration.FILE_PORT));
socketChannel = serverSocketChannel.accept();
System.out.println("Connection established...." + socketChannel.getRemoteAddress());
} catch (IOException e) {
e.printStackTrace();
}
return socketChannel;
}
/**
* Reads the bytes from socket and writes to file
*
* #param socketChannel
*/
public void readFileFromSocket(SocketChannel socketChannel) {
RandomAccessFile aFile = null;
try {
aFile = new RandomAccessFile(this.fileName, "rw");
ByteBuffer buffer = ByteBuffer.allocate(1024);
FileChannel fileChannel = aFile.getChannel();
while (socketChannel.read(buffer) > 0) {
buffer.flip();
fileChannel.write(buffer);
buffer.clear();
}
// Thread.sleep(1000);
fileChannel.close();
System.out.println("End of file reached..Closing channel");
socketChannel.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}/*} catch (InterruptedException e) {
e.printStackTrace();
}*/
}

You need to send the length, and probably the name, ahead of the file, so the receiver knows when to stop. The receiver has to make sure to only read exactly that many bytes, which may require reducing the limit on the last read. In addition your copy loops are incorrect:
while (inChannel.read(buffer) > 0) {
buffer.flip();
socketChannel.write(buffer);
buffer.clear();
}
This doesn't necessarily work correctly at end of stream. It should be:
while (inChannel.read(buffer) >= 0 || buffer.position() > 0) {
buffer.flip();
socketChannel.write(buffer);
buffer.compact(); // NB compact(), not clear()
}
noting again that they will need further modification as described above.

Related

Multiple invalid stream header

I have problems with ByteArray and Object streams. I'm creating a multiplayer card game via NIO server. I send the ArrayList private ArrayList<Card> cardsDropped through the method:
public void sendMessage(Object message) {
if (message instanceof String) {
messages.add(message + Config.MESSAGE_DELIMITER);
} else {
messages.add(message);
}
SelectionKey key = channel.keyFor(selector);
key.interestOps(OP_WRITE);
}
With private final LinkedList<Object> messages that is the list of all objects sent in the stream through
-> Client methods:
protected void handleIncomingData(SelectionKey sender, byte[] data) throws IOException {
ByteArrayInputStream byteObject = new ByteArrayInputStream(data);
ObjectInputStream obj;
in = null;
try {
obj = new ObjectInputStream(byteObject); //HERE <--
byteObject.close();
in = obj.readObject();
obj.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
handler.onMessage(in);
}
protected void write(SelectionKey key) {
SocketChannel channel = (SocketChannel) key.channel();
while (!messages.isEmpty()) {
ByteArrayOutputStream byteObject = new ByteArrayOutputStream();
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(byteObject);
oos.writeObject(messages.poll());
oos.flush(); //TODO ?
oos.close();
channel.write(ByteBuffer.wrap(byteObject.toByteArray()));
byteObject.close();
} catch (IOException e) {
e.printStackTrace();
}
}
key.interestOps(OP_READ);
}
And Server methods:
protected void write(SelectionKey key) {
ByteBuffer buffer = (ByteBuffer) key.attachment();
SocketChannel channel = (SocketChannel) key.channel();
try {
channel.write(buffer);
} catch (IOException e) {
e.printStackTrace();
}
}
protected void handleIncomingData(SelectionKey sender, byte[] data) throws IOException {
for (SelectionKey key : selector.keys()) {
if (key.channel() instanceof ServerSocketChannel) {
continue;
}
if (key.equals(sender)) {
continue;
}
key.attach(ByteBuffer.wrap(data));
write(key);
}
}
After some turns and cards sent, Client thread is sending me some "invalid stream header" here obj = new ObjectInputStream(byteObject);
Is this a problem related to how is the server/client code written? [The code is based on https://github.com/mpkelly/nio-chat ]
Thanks in advance!

Why does my TCP connection close after running a command? - Java

I have a simple FTP server and client. For now, the client can send a file, and the server can accept it, but after i run a sendFile() command, it transfers the file, and the server and the client terminate, making it unable to run any other commands after that.
SERVER
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;
import mmd.filetransfer.FileEvent;
public class Server {
private ServerSocket serverSocket = null;
private Socket socket = null;
private ObjectInputStream inputStream = null;
private FileEvent fileEvent;
private File dstFile = null;
private FileOutputStream fileOutputStream = null;
public Server() {
}
/**
  * Accepts socket connection
  */
public void doConnect() {
try {
serverSocket = new ServerSocket(4445);
socket = serverSocket.accept();
inputStream = new ObjectInputStream(socket.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
/**
  * Reading the FileEvent object and copying the file to disk.
  */
public void downloadFile() {
try {
fileEvent = (FileEvent) inputStream.readObject();
if (fileEvent.getStatus().equalsIgnoreCase("Error")) {
System.out.println("Error occurred ..So exiting");
System.exit(0);
}
String outputFile = fileEvent.getDestinationDirectory() + fileEvent.getFilename();
if (!new File(fileEvent.getDestinationDirectory()).exists()) {
new File(fileEvent.getDestinationDirectory()).mkdirs();
}
dstFile = new File(outputFile);
fileOutputStream = new FileOutputStream(dstFile);
fileOutputStream.write(fileEvent.getFileData());
fileOutputStream.flush();
fileOutputStream.close();
System.out.println("Output file : " + outputFile + " is successfully saved ");
//Thread.sleep(0);
//System.exit(0);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Server server = new Server();
server.doConnect();
server.downloadFile();
}
}
CLIENT
package mmd.client;
import java.io.*;
import java.net.Socket;
import mmd.filetransfer.FileEvent;
public class Client {
private Socket socket = null;
private ObjectOutputStream outputStream = null;
private boolean isConnected = false;
private String sourceFilePath = "/home/jovan/Desktop/videot.mpg";
private FileEvent fileEvent = null;
private String destinationPath = "/home/jovan/Desktop/tp/";
public Client() {
}
/**
  * Connect with server code running in local host or in any other host
  */
public void connect() {
while (!isConnected) {
try {
socket = new Socket("localHost", 4445);
outputStream = new ObjectOutputStream(socket.getOutputStream());
isConnected = true;
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void sendFile() {
fileEvent = new FileEvent();
String fileName = sourceFilePath.substring(sourceFilePath.lastIndexOf("/") + 1, sourceFilePath.length());
String path = sourceFilePath.substring(0, sourceFilePath.lastIndexOf("/") + 1);
fileEvent.setDestinationDirectory(destinationPath);
fileEvent.setFilename(fileName);
fileEvent.setSourceDirectory(sourceFilePath);
File file = new File(sourceFilePath);
if (file.isFile()) {
try {
DataInputStream diStream = new DataInputStream(new FileInputStream(file));
long len = (int) file.length();
byte[] fileBytes = new byte[(int) len];
int read = 0;
int numRead = 0;
while (read < fileBytes.length && (numRead = diStream.read(fileBytes, read,
fileBytes.length - read)) >= 0) {
read = read + numRead;
}
fileEvent.setFileSize(len);
fileEvent.setFileData(fileBytes);
fileEvent.setStatus("Success");
} catch (Exception e) {
e.printStackTrace();
fileEvent.setStatus("Error");
}
} else {
System.out.println("path specified is not pointing to a file");
fileEvent.setStatus("Error");
}
//Now writing the FileEvent object to socket
try {
outputStream.writeObject(fileEvent);
System.out.println("Done...Going to exit");
Thread.sleep(0);
//System.exit(0);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
  * Sending FileEvent object.
 
* #throws IOException */
public static void main(String[] args){
Client client = new Client();
client.connect();
client.sendFile();
client.sendFile();
}
}
How to prevent this?
Calling it an FTP server is a bit confusing, as this does not implement RFC 959.
Your main() in the server code does not have any loop. It just listens, transfers one file and exits. Put it in an infinite loop as ravindra suggests.

Simple Client-Server Program with NIO channels

SOLVED
If anyone would be interested I could edit this post with correct data. Just leave a comment.
As my assignment I had to create a simple server and a client using non-blocking channels and selectors.
Basically it should either echo the message written by the client or add two numbers(also provided by the client).
My problem is that I get errors at point where the message is about to be echoed by server.
I have checked if msg gets to writeResponse method, and it does. So that's where the problem starts.
Thank you all in advance !
Errors I get:
java.io.IOException: An existing connection was forcibly closed by the remote host
at sun.nio.ch.SocketDispatcher.read0(Native Method)
at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:43)
at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:218)
at sun.nio.ch.IOUtil.read(IOUtil.java:191)
at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:359)
at SimpleServer.serviceRequest(SimpleServer.java:89)
at SimpleServer.serviceConnections(SimpleServer.java:61)
at SimpleServer.<init>(SimpleServer.java:35)
at SimpleServer.main(SimpleServer.java:141)
Server:
public class SimpleServer {
private ServerSocketChannel ssc = null; //for multiplexing
private Selector selector = null; //monitors channels
private static Charset charset = Charset.defaultCharset();//encoding
private static final int BSIZE = 1024;//buffer size
private ByteBuffer bbuf = ByteBuffer.allocate(BSIZE);
private StringBuffer reqString = new StringBuffer();
public SimpleServer(String host, int port) {
try {
ssc = ServerSocketChannel.open();
ssc.configureBlocking(false);
ssc.socket().bind(new InetSocketAddress(host, port));
selector = Selector.open(); //selector initiation
ssc.register(selector, SelectionKey.OP_ACCEPT); //registering communication channel
} catch(Exception exc) {
exc.printStackTrace();
System.out.println(1);
}
System.out.println("Server started and is ready for requests");
serviceConnections();
}//constructor
private void serviceConnections() {
boolean serverIsRunning = true;
while(serverIsRunning) {
try {
selector.select();//waits for answer from selector
Set<SelectionKey> keys = selector.selectedKeys(); //set of keys
Iterator<SelectionKey> iter = keys.iterator(); //iterration throught set of keys
while(iter.hasNext()) {
SelectionKey key = (SelectionKey) iter.next(); //obtain key
iter.remove(); //remove, because we'd get it again
if(key.isAcceptable()) {
SocketChannel cc = ssc.accept();//obtaining channel for communication
cc.configureBlocking(false);
cc.register(selector, SelectionKey.OP_READ); //registering selector for monitoring
continue;
}
if(key.isReadable()) { //channel with readable data
SocketChannel cc = (SocketChannel) key.channel();
serviceRequest(cc);
continue;
}
}//while loop
} catch(Exception exc) {
exc.printStackTrace();
continue;
}
}//outer while loop
}//serviceCconnection method
private void serviceRequest(SocketChannel sc) {
if(!sc.isOpen()) return;
reqString.setLength(0);
bbuf.clear();
try {
readLoop:
while (true) {
int n = sc.read(bbuf);
if(n > 0) {
bbuf.flip();//set limit, return to beginning
CharBuffer cbuf = charset.decode(bbuf);
while(cbuf.hasRemaining()) {
char c = cbuf.get();
if (c == '\r' || c == '\n') break readLoop;
reqString.append(c);
}
}
}//while loop
String[] req = reqString.toString().split(" ");
String cmd = req[0];
if (cmd.equals("bye")) {
sc.close();
sc.socket().close();
}
else if(cmd.equals("echo"))
writeResp(sc, reqString.toString());
else if(cmd.equals("add"))
writeResp(sc, Integer.parseInt(req[1]),Integer.parseInt( req[2]));
} catch (Exception exc) {
exc.printStackTrace();
try { sc.close();
sc.socket().close();
} catch (Exception e) {}
}
}//serviceRequest
//overloaded methods
public void writeResp(SocketChannel sc, String msg) throws IOException {
System.out.println(msg);
ByteBuffer cbuf = charset.encode(CharBuffer.wrap(msg));
cbuf = ByteBuffer.allocate(1024);
cbuf.put(msg.getBytes());
cbuf.rewind();
sc.write(cbuf);
}//writeResp method
public void writeResp(SocketChannel sc, int i, int j) throws IOException, NumberFormatException {
int ans = i + j;
String resp = Integer.toString(ans);
ByteBuffer cbuf = charset.encode(CharBuffer.wrap(resp));
sc.write(cbuf);
}//write Resp method
public static void main(String[] args) {
try {
String host = "localhost";
int port = 9998;
new SimpleServer(host, port);
} catch(Exception exc) {
exc.printStackTrace();
System.out.println(1);
}
}//main
}//class
My client:
public class SimpleClient {
private SocketChannel sc;
private static Charset charset;
private StringBuffer reqString = new StringBuffer();
private ByteBuffer bb;
String msg;
public SimpleClient(String host, int port) throws IOException, InterruptedException {
try {
sc = SocketChannel.open();
sc.configureBlocking(false);
sc.connect(new InetSocketAddress(host, port));
System.out.println("Connecting to the server...");
while(!sc.finishConnect()) {
System.out.println("Connection is being established...");
}
} catch (IOException exc) {
System.out.println("IO exception");
System.exit(1);
}
System.out.println("Connection Established!");
makeRequest("echo Test input stream\n");
Thread.sleep(500);
readRequest();
}//constructor
private void makeRequest(String req) throws IOException {
System.out.println("Request: " + req);
bb = ByteBuffer.allocate(1024);
bb.put(req.getBytes());
bb.rewind();
sc.write(bb);
}//makeRequest method
public void readRequest() throws IOException, InterruptedException {
reqString.setLength(0);
bb.clear();
try {
readLoop:
while (true) {
bb.clear();
int readBytes = sc.read(bb);
if(readBytes == 0){
System.out.println("waiting for data");
continue;
}
else if(readBytes == -1) {
System.out.println("Server not responding");
break;
}
else {
bb.flip();
CharBuffer cbuf = charset.decode(bb);
while(cbuf.hasRemaining()) {
char c = cbuf.get();
if (c == '\r' || c == '\n') break readLoop;
reqString.append(c);
}
}
}//while loop
System.out.println(reqString.toString());
} catch( Exception exc) {//while loop
exc.printStackTrace();
}
}//readRequest method
public static void main(String[] args) {
try {
new SimpleClient("localhost", 9998);
}catch (IOException exc) {
exc.printStackTrace();
}catch(InterruptedException exc) {
exc.printStackTrace();
}
}//main method
}//class
If read() returns -1 it doesn't mean 'server not responding'. It means the peer has closed the connection, and you should do likewise. Instead you aren't closing it at all, so the operating system does a reset, so your server gets this exception.

Sending audio stream over TCP, UnsupportedAudioFileException

I have succeeded with sending and reading text and images data over TCP sockets. But I am unable to sending and reading audio stream data.
sample code at server:
public class ServerAudio {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
ServerSocket serverSocker = new ServerSocket();
Socket client = null;
serverSocker.bind(new InetSocketAddress(6666));
if (serverSocker.isBound()) {
client = serverSocker.accept();
OutputStream out = client.getOutputStream();
while (true) {
AudioInputStream ain = testPlay("C:/Users/Public/Music/Sample Music/adios.wav");
if (ain != null) {
AudioSystem.write(ain, AudioFileFormat.Type.WAVE, out);
}
}
}
serverSocker.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static AudioInputStream testPlay(String filename) {
AudioInputStream din = null;
try {
File file = new File(filename);
AudioInputStream in = AudioSystem.getAudioInputStream(file);
System.out.println("Before :: " + in.available());
AudioFormat baseFormat = in.getFormat();
AudioFormat decodedFormat =
new AudioFormat(AudioFormat.Encoding.PCM_UNSIGNED, baseFormat.getSampleRate(),
8, baseFormat.getChannels(), baseFormat.getChannels(),
baseFormat.getSampleRate(), false);
din = AudioSystem.getAudioInputStream(decodedFormat, in);
System.out.println("After :: " + din.available());
return din;
} catch (Exception e) {
// Handle exception.
e.printStackTrace();
}
return din;
}
}
sample code at client:
public class RDPPlayAudioBytes {
private static Socket socket;
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
// SocketAddress socketAddress = new InetSocketAddress("172.19.1.50", 4444);
try {
Socket socket = new Socket("172.19.0.109", 6666);
// socket.connect(socketAddress, 10000);
if (socket != null && socket.isConnected()) {
InputStream inputStream = socket.getInputStream();
// DataInputStream din=new DataInputStream(inputStream);
while (inputStream != null) {
if (inputStream.available() > 0) {
System.out.println(inputStream.available());
InputStream bufferedIn = new BufferedInputStream(inputStream);
System.out.println("********** Buffred *********" + bufferedIn.available());
AudioInputStream ais = AudioSystem.getAudioInputStream(bufferedIn);
}
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} /*
* catch (LineUnavailableException e) { // TODO Auto-generated catch block
* e.printStackTrace(); }
*/catch (UnsupportedAudioFileException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Where I am getting Exception as
javax.sound.sampled.UnsupportedAudioFileException: could not get audio input stream from input stream
at javax.sound.sampled.AudioSystem.getAudioInputStream(Unknown Source)
Where I have observed that server is sending 35394bytes data to client, But at client side we are receiving 8192 bytes data. I am unable to understanding why bytes are missing at client side.
Please help me how to send audio stream over TCP Sockets.
The Server: The server just streams the bytes of a sound file. No AudioSytem involved. Pass the sound file as argument:
java AudioServer "C:/Users/Public/Music/Sample Music/adios.wav"
Code for class AudioServer:
import java.io.*;
import java.net.*;
public class AudioServer {
public static void main(String[] args) throws IOException {
if (args.length == 0)
throw new IllegalArgumentException("expected sound file arg");
File soundFile = AudioUtil.getSoundFile(args[0]);
System.out.println("server: " + soundFile);
try (ServerSocket serverSocker = new ServerSocket(6666);
FileInputStream in = new FileInputStream(soundFile)) {
if (serverSocker.isBound()) {
Socket client = serverSocker.accept();
OutputStream out = client.getOutputStream();
byte buffer[] = new byte[2048];
int count;
while ((count = in.read(buffer)) != -1)
out.write(buffer, 0, count);
}
}
System.out.println("server: shutdown");
}
}
The client: The client can play a soundfile passed via the command-line for testing if it works:
java AudioClient "C:/Users/Public/Music/Sample Music/adios.wav"
Called with no argument it connects to the server and plays the file received via an Socket:
java AudioClient
Code:
import java.io.*;
import java.net.*;
import javax.sound.sampled.*;
public class AudioClient {
public static void main(String[] args) throws Exception {
if (args.length > 0) {
// play a file passed via the command line
File soundFile = AudioUtil.getSoundFile(args[0]);
System.out.println("Client: " + soundFile);
try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(soundFile))) {
play(in);
}
}
else {
// play soundfile from server
System.out.println("Client: reading from 127.0.0.1:6666");
try (Socket socket = new Socket("127.0.0.1", 6666)) {
if (socket.isConnected()) {
InputStream in = new BufferedInputStream(socket.getInputStream());
play(in);
}
}
}
System.out.println("Client: end");
}
private static synchronized void play(final InputStream in) throws Exception {
AudioInputStream ais = AudioSystem.getAudioInputStream(in);
try (Clip clip = AudioSystem.getClip()) {
clip.open(ais);
clip.start();
Thread.sleep(100); // given clip.drain a chance to start
clip.drain();
}
}
}
A utility class used by AudioServer and AudioClient:
import java.io.File;
public class AudioUtil {
public static File getSoundFile(String fileName) {
File soundFile = new File(fileName);
if (!soundFile.exists() || !soundFile.isFile())
throw new IllegalArgumentException("not a file: " + soundFile);
return soundFile;
}
}
The bytes will be received completely as TCP is reliable. There is another small issue. You need to play the received audio from the audio stream, only creating an audio input stream will not play it.
There can be different possible techniques for playing the audio received. You can use a Clip or SourceDataLine from the Java Sound API. Also, do not create the AudioInputStream multiple times. Simply create it once and use it.
Here's one of the possible solution you can use for playing the received audio.
public class RDPPlayAudioBytes {
private static Socket socket;
private static BufferedInputStream inputStream;
/**
* #param args
* #throws javax.sound.sampled.LineUnavailableException
*/
public static void main(String[] args) throws LineUnavailableException {
// TODO Auto-generated method stub
// SocketAddress socketAddress = new InetSocketAddress("172.19.1.50", 4444);
try {
socket = new Socket("127.0.0.1", 6666);
if (socket.isConnected()) {
inputStream = new BufferedInputStream(socket.getInputStream());
Clip clip = AudioSystem.getClip();
AudioInputStream ais = AudioSystem.getAudioInputStream(inputStream);
clip.open(ais);
clip.start();
while (inputStream != null) {
if (clip.isActive()) {
System.out.println("********** Buffred *********" + inputStream.available());
}
}
}
} catch (IOException | UnsupportedAudioFileException e) {
System.err.println(e);
}
}
}
You may need a different implementation based on your requirement. This is just a demonstration on how you can use the AudioInputStream for playing audio using Clip. You may notice quite a few changes in the code I have posted. I hope you understand this well.
You may refer the Java Sound API docs to dive into the basics of playing audio.
NOTE:
Just for your knowledge, you may need to implement a listener so that the program do not get closed before the audio clip finishes playing. In the current implementation it won't happen due to the loop used. But it is better to use a listener. You may refer this post.
You can also read the audio data into byte[] and then play it as soon as it is received. The implementation would change slightly.

Threads are facing deadlock in socket program

I am developing one program in which a user can download a number of files. Now first I am sending the list of files to the user. So from the list user selects one file at a time and provides path where to store that file. In turn it also gives the server the path of file where does it exist.
I am following this approach because I want to give stream like experience without file size limitation.
Here is my code..
1) This is server which gets started each time I start my application
public class FileServer extends Thread {
private ServerSocket socket = null;
public FileServer() {
try {
socket = new ServerSocket(Utils.tcp_port);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void run() {
try {
System.out.println("request received");
new FileThread(socket.accept()).start();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
2) This thread runs for each client separately and sends the requested file to the user 8kb data at a time.
public class FileThread extends Thread {
private Socket socket;
private String filePath;
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
public FileThread(Socket socket) {
this.socket = socket;
System.out.println("server thread" + this.socket.isConnected());
//this.filePath = filePath;
}
#Override
public void run() {
// TODO Auto-generated method stub
try
{
ObjectInputStream ois=new ObjectInputStream(socket.getInputStream());
try {
//************NOTE
filePath=(String) ois.readObject();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
File f = new File(this.filePath);
byte[] buf = new byte[8192];
InputStream is = new FileInputStream(f);
BufferedInputStream bis = new BufferedInputStream(is);
ObjectOutputStream oos = new ObjectOutputStream(
socket.getOutputStream());
int c = 0;
while ((c = bis.read(buf, 0, buf.length)) > 0) {
oos.write(buf, 0, c);
oos.flush();
// buf=new byte[8192];
}
oos.close();
//socket.shutdownOutput();
// client.shutdownOutput();
System.out.println("stop");
// client.shutdownOutput();
ois.close();
// Thread.sleep(500);
is.close();
bis.close();
socket.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
NOTE: here filePath represents the path of the file where it exists on the server. The client who is connecting to the server provides this path. I am managing this through sockets and I am successfully receiving this path.
3) FileReceiverThread is responsible for receiving the data from the server and constructing file from this buffer data.
public class FileReceiveThread extends Thread {
private String fileStorePath;
private String sourceFile;
private Socket socket = null;
public FileReceiveThread(String ip, int port, String fileStorePath,
String sourceFile) {
this.fileStorePath = fileStorePath;
this.sourceFile = sourceFile;
try {
socket = new Socket(ip, port);
System.out.println("receive file thread " + socket.isConnected());
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public void run() {
try {
ObjectOutputStream oos = new ObjectOutputStream(
socket.getOutputStream());
oos.writeObject(sourceFile);
oos.flush();
// oos.close();
File f = new File(fileStorePath);
OutputStream os = new FileOutputStream(f);
BufferedOutputStream bos = new BufferedOutputStream(os);
byte[] buf = new byte[8192];
int c = 0;
//************ NOTE
ObjectInputStream ois = new ObjectInputStream(
socket.getInputStream());
while ((c = ois.read(buf, 0, buf.length)) > 0) {
// ois.read(buf);
bos.write(buf, 0, c);
bos.flush();
// buf = new byte[8192];
}
ois.close();
oos.close();
//
os.close();
bos.close();
socket.close();
//Thread.sleep(500);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
NOTE : Now the problem that I am facing is at the first time when the file is requested the outcome of the program is same as my expectation. I am able to transmit any size of file at first time. Now when the second file is requested (e.g. I have sent file a,b,c,d to the user and user has received file a successfully and now he is requesting file b) the program faces deadlock at this situation. It is waiting for socket's input stream. I put breakpoint and tried to debug it but it is not going in FileThread's run method second time. I could not find out the mistake here. Basically I am making a LAN Messenger which works on LAN. I am using SWT as UI framework.
A more basic problem.
You are only processing the first socket.
while(true) {
new FileThread(socket.accept()).start();
}
As per the suggestion of Peter Lawrey i removed all the redundant streams code from my source code. Now the changed source code is as follows and the problem remains.
1) No change in FileServer. It is as it is .
2) FileThread
public class FileThread extends Thread {
private Socket socket;
private String filePath;
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
public FileThread(Socket socket) {
this.socket = socket;
System.out.println("server thread" + this.socket.isConnected());
// this.filePath = filePath;
}
#Override
public void run() {
// TODO Auto-generated method stub
try
{
OutputStream oos = socket.getOutputStream();
oos.flush();
InputStream ois = socket.getInputStream();
byte[] buf = new byte[8192];
ois.read(buf);
filePath = new String(buf);
System.out.println(filePath);
File f = new File(this.filePath);
InputStream is = new FileInputStream(f);
int c = 0;
while ((c = is.read(buf, 0, buf.length)) > 0) {
oos.write(buf, 0, c);
oos.flush();
}
oos.close();
System.out.println("stop");
ois.close();
is.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
3) FileReceiverThread
public class FileReceiveThread extends Thread {
private String fileStorePath;
private String sourceFile;
private Socket socket = null;
public FileReceiveThread(String ip, int port, String fileStorePath,
String sourceFile) {
this.fileStorePath = fileStorePath;
this.sourceFile = sourceFile;
try {
socket = new Socket(ip, port);
System.out.println("receive file thread " + socket.isConnected());
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public void run() {
try {
OutputStream oos = socket.getOutputStream();
oos.write(sourceFile.getBytes());
oos.flush();
File f = new File(fileStorePath);
OutputStream os = new FileOutputStream(f);
byte[] buf = new byte[8192];
int c = 0;
// ************ NOTE
InputStream ois = socket.getInputStream();
while ((c = ois.read(buf, 0, buf.length)) > 0) {
os.write(buf, 0, c);
os.flush();
}
ois.close();
oos.close();
os.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
is there still something which i am missing ?

Categories

Resources