オーディオ ストリーミング用のクライアント/サーバー システムを実装しようとしています。クライアントはファイルを要求し、サーバーはそれを送信する必要があります。その後、クライアントはすぐにファイルを再生する必要があります。rtp および rtsp プロトコルに基づくいくつかのソリューションを読みましたが、それらは私のユース ケースには複雑すぎます。TCP ソケットを介した単純なファイル転送を使用したいのですが、クライアントはダウンロードの終了を待たずにすぐにオーディオ ファイルを再生する必要があります。この解決策は可能ですか?
これは私が使用しているコードです。
サーバ:
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
public class ConcurTCPServer implements Runnable
{
static ServerSocket listenSocket;
Socket sock = null;
static final int port = 12345;
InputStream recvStream = null;
OutputStream sendStream = null;
FileInputStream fis = null;
BufferedInputStream bis = null;
String request;
String response;
public ConcurTCPServer(Socket s) throws IOException, UnknownHostException
{
sock = s;
recvStream = sock.getInputStream();
sendStream = sock.getOutputStream();
}
public void run()
{
getRequest();
process();
sendResponse();
close();
}
void getRequest()
{
try
{
int dataSize;
byte[] recvBuff = new byte[1024];
dataSize = recvStream.read(recvBuff, 0, 1024);
request = new String(recvBuff, 0, dataSize);
System.out.println("Request for: " + request);
}
catch (IOException ex)
{
ex.printStackTrace();
}
}
void process()
{
//TODO
}
void sendResponse()
{
try
{
File myFile = new File ("/Users/user/Desktop/" + request);
byte [] mybytearray = new byte [(int)myFile.length()];
fis = new FileInputStream(myFile);
bis = new BufferedInputStream(fis);
bis.read(mybytearray,0,mybytearray.length);
System.out.println("Sending..." + myFile.getPath() + ". Dimension: " + myFile.length());
sendStream.write(mybytearray,0,mybytearray.length);
sendStream.flush();
}
catch (IOException e)
{
e.printStackTrace();
}
}
void close()
{
try
{
System.out.println("Done");
recvStream.close();
sendStream.close();
sock.close();
}
catch (IOException ex)
{
ex.printStackTrace();
}
}
public static void main(String [] args) throws IOException
{
listenSocket = new ServerSocket(port);
while(true)
{
System.out.println("Waiting...");
ConcurTCPServer server = new ConcurTCPServer(listenSocket.accept());
System.out.println("Client connected");
Thread thread = new Thread(server);
thread.start();
}
}
}
クライアント:
import java.net.*;
import java.io.*;
import sun.audio.AudioData;
import sun.audio.AudioDataStream;
import sun.audio.AudioPlayer;
import sun.audio.AudioStream;
public class TCPClient
{
Socket sock;
OutputStream sendStream;
InputStream recvStream;
AudioStream audioStream;
AudioData audiodata;
AudioDataStream audioDataStream;
String request;
String response;
public TCPClient(String server, int port) throws IOException, UnknownHostException
{
sock = new Socket(server, port);
sendStream = sock.getOutputStream();
recvStream = sock.getInputStream();
}
void makeRequest(String word)
{
request = word;
}
void sendRequest()
{
try
{
byte[] sendBuff = new byte[request.length()];
sendBuff = request.getBytes();
System.out.println("Sending request for: " + request);
sendStream.write(sendBuff, 0, sendBuff.length);
}
catch (IOException ex)
{
ex.printStackTrace();
}
}
void getResponse()
{
try
{
System.out.println("Playing...");
audioStream = new AudioStream(recvStream);
audiodata = audioStream.getData();
audioDataStream = new AudioDataStream(audiodata);
AudioPlayer.player.start(audioDataStream);
}
catch (IOException e)
{
e.printStackTrace();
}
}
void close()
{
try
{
System.out.println("Done");
if (audioStream != null) audioStream.close();
sendStream.close();
recvStream.close();
sock.close();
}
catch (IOException ex)
{
ex.printStackTrace();
}
}
public static void main(String[] args) throws IOException
{
final int servPort = 12345;
final String servName = "localhost";
TCPClient client = new TCPClient(servName, servPort);
System.out.println("Connected");
client.makeRequest("welcome.wav");
client.sendRequest();
client.getResponse();
client.close();
}
}
小さな .wav でしか動作しないので、実際にファイルをストリーミング再生するわけではないと思いますが、ダウンロード後すぐに再生が始まります。ファイル サイズが約 1Mb 以上の場合、クライアントは例外を返します。
java.io.IOException: could not create AudioData object
at sun.audio.AudioStream.getData(AudioStream.java:125)
at com.dicet.unisalento.TCPClient.getResponse(TCPClient.java:54)
at com.dicet.unisalento.TCPClient.main(TCPClient.java:88)
一方、サーバーは例外を返します。
java.net.SocketException: Broken pipe
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:113)
at java.net.SocketOutputStream.write(SocketOutputStream.java:159)
at com.dicet.unisalento.ConcurTCPServer.sendResponse(ConcurTCPServer.java:70)
at com.dicet.unisalento.ConcurTCPServer.run(ConcurTCPServer.java:35)
at java.lang.Thread.run(Thread.java:744)
助けてください。
周りを見回すと、HTTP プログレッシブ ダウンロードを使用する必要があることがわかりましたが、HTTP プログレッシブ ダウンロードを使用したクライアント/サーバーの実装例が見つかりません。