I'm trying to transmit real time mic recording to server over TCP socket and server to write input stream to a file. The connection is established but after some time, I'm getting connection refused error at my clientside.
Server Code:
public class auServer extends Thread{
private static ServerSocket serverSocket;
private static int port = 3333;
public void run()
{
System.out.println("init success");
while(true)
{
try
{
serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(10000);
Socket clientSoc = serverSocket.accept();
System.out.println("Waiting for client on port " +serverSocket.getLocalPort() + "...");
System.out.println("Just connected to " + clientSoc.getRemoteSocketAddress());
InputStream in = clientSoc.getInputStream();
while(in!=null)
{
writeToFile(in);
}
System.out.println("socket");
clientSoc.close();
}catch(SocketTimeoutException s)
{
System.out.println("Socket timed out!");
break;
}catch(IOException e)
{
e.printStackTrace();
System.out.println("some io");
break;
} catch (Exception e) {
System.out.println("some e");
e.printStackTrace();
}
}
}
private void writeToFile(InputStream in) throws IOException {
// Write the output audio in byte
String filePath = "8k16bitMono1.wav";
short sData[] = new short[1024];
byte[] bData = IOUtils.toByteArray(in);
FileOutputStream os = null;
try {
os = new FileOutputStream(filePath);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
System.out.println("Short wirting to file" + sData.toString());
try {
os.write(bData, 0, 2048);
} catch (IOException e) {
e.printStackTrace();
}
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
try
{
Thread serverThread = new auServer();
serverThread.run();
System.out.println("runing");
}catch(IOException e){
e.printStackTrace();
}
}
}
and Client :
private void streamData(byte[] bData) throws UnknownHostException, IOException, InterruptedException { //bData is byte array to transmit
Thread.sleep(500);
Socket client = new Socket("10.221.40.41",3333);
OutputStream outToServer = client.getOutputStream();
outToServer.write(bData);
if(!isRecording)
client.close();
}
What could be the problem? Thanks in advance.
for reading and writing on the same socket concurrently there is no problem, what really will happenn is that, you first when connect to the server using Socket, you must get output and input streams from this Socket object for writing and reading, then you can make a thread that listening for incoming messages from ...
You can send and recv from any connected socket. The direction of the data flow does not have anything to do with the client/server relationship. It is very common for clients and servers to both send and receive.
In a connection-oriented client-to-server model, the socket on the server process waits for requests from a client. To do this, the server first establishes (binds) an address that clients can use to find the server. When the address is established, the server waits for clients to request a service.
I'll comment on your code piece by piece.
private static ServerSocket serverSocket;
There's no reason for this to be static.
while(true)
{
try
{
serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(10000);
The last two lines should be ahead of the loop. This is the reason for the connection refusals, and it will also cause BindExceptions
that you haven't mentioned. It isn't clear why you need the timeout.
Socket clientSoc = serverSocket.accept();
System.out.println("Waiting for client on port " +serverSocket.getLocalPort() + "...");
No you aren't. He's already connected. You were waiting before the accept().
System.out.println("Just connected to " + clientSoc.getRemoteSocketAddress());
InputStream in = clientSoc.getInputStream();
while(in!=null)
Both the loop and the test are futile. The variable isn't null initially, and there is no way it can ever become null. The loop is futile because the writeToFile()
method completely exhausts the input stream, so there is never anything more to read. This will be causing junk data, which you haven't mentioned.
{
writeToFile(in);
}
System.out.println("socket");
A pointless message.
clientSoc.close();
All the code from the line after accept()
to here should be executed in a separate thread. The accept loop should do nothing but accept connections and start threads.
}catch(SocketTimeoutException s)
{
System.out.println("Socket timed out!");
What timed out here was the accept()
, as the listening socket is the only socket you've set a timeout on. I doubt that you need this.
break;
}catch(IOException e)
{
e.printStackTrace();
System.out.println("some io");
Another futile message.
break;
} catch (Exception e) {
System.out.println("some e");
Yet another one. When you get an exception, print the exception. Not some futile message of your own devising. Otherwise debugging becomes a mere guessing game.
e.printStackTrace();
}
}
}
private void writeToFile(InputStream in) throws IOException {
// Write the output audio in byte
String filePath = "8k16bitMono1.wav";
short sData[] = new short[1024];
Unused. Remove.
byte[] bData = IOUtils.toByteArray(in);
Don't use this. It wastes space and adds latency. See below for the correct solution.
FileOutputStream os = null;
try {
os = new FileOutputStream(filePath);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Poor technique. This catch
is in the wrong place. Code that depends on the success of code in a try
block should be inside the same try
block. At present you are falling through this try-catch
as though the exception never happened, which will cause a NullPointerException
in the code below.
System.out.println("Short wirting to file" + sData.toString());
Another pointless message. Misspelt; sData
has nothing in it; sData.toString()
doesn't print anything useful regardless of the contents; and incorrect, as you aren't writing sData
at all.
try {
os.write(bData, 0, 2048);
This writes exactly 2048 bytes, regardless of the amount read, which could be less or more. If it was less it will throw an ArrayIndexOutOfBoundsException
or similar, which I would expect to see on the second call, although you haven't mentioned it, because the array should be zero length on the second and subsequent calls, if any. It should be a loop, of the general form:
int count;
byte[] buffer = new byte[8192]; // or more if you like
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
Back to your code:
} catch (IOException e) {
e.printStackTrace();
}
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
try
{
Thread serverThread = new auServer();
serverThread.run();
This runs the run()
method of the thread. It doesn't start a thread. It should be serverThread.start().
System.out.println("runing");
Misspelt. Until you fix the start/run problem above, you won't see this message until after the server's run()
method has exited.
and Client :
private void streamData(byte[] bData) throws UnknownHostException, IOException, InterruptedException { //bData is byte array to transmit
Thread.sleep(500);
Pointless. Remove. Don't put sleeps into networking code.
Socket client = new Socket("10.221.40.41",3333);
Don't create a new connection per buffer. Use the same connection for the life of the client.
OutputStream outToServer = client.getOutputStream();
outToServer.write(bData);
if(!isRecording)
client.close();
This should be unconditional, and it should be elsewhere, along with the creation of the socket.
What could be the problem?
Problems. Plural. Multiple. See above.
The creation of the serversocket must be done outside of the loop. And for parallel connections you need to start a thread per connection.
Also apply the timeout to the established connections. A timeout on the serverSocket will end accepting after the timeout, this is nothing you want in a server.
...
public void run() {
ServerSocket serverSocket;
try {
serverSocket = new ServerSocket(port);
} catch (Exception ex) {
ex.printStackTrace();
return;
}
System.out.println("init success");
while (true) {
try {
System.out.println("Waiting for client on port " + serverSocket.getLocalPort() + "...");
final Socket clientSoc = serverSocket.accept();
clientSoc.setSoTimeout(10000);
System.out.println("Just connected to " + clientSoc.getRemoteSocketAddress());
new Thread() {
public void run() {
try {
InputStream in = clientSoc.getInputStream();
writeToFile(in);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
clientSoc.close();
} catch (Exception ignore) {
}
}
}
}.start();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
...
I'm guessing your client side is an android application. Once, I tried to read and write data to an android application through a socket connection. Eventually, I did it by using the adb(android debugger bridge).
Lets say, there is a java application which creates a Socket
with the port number 1992. And there is an android application, which creates a ServerSocket
with the port number 1993.
Here comes the real deal!
Before you start running applications, you need to execute the following command in adb shell (or you can locate your adb in cmd/terminal and execute the command)
adb forward tcp:1992 tcp:1993
After forwarding the port you can write and read data from java application to android application and wise-versa, using sockets' IO streams.
Desktop application code snippet :
while (flag) {
try {
final Socket socket = new Socket("localhost", 1992);
new Thread(){
@Override
public void run() {
while (flag) {
try {
new PrintWriter(socket.getOutputStream(), true).println(new Date().toString());
} catch (IOException ex) {
break;
}
}
}
}.start();
} catch (IOException ex) {
// need port-forwarding
}
}
Android application code snippet :
while (flag) {
try {
final Socket socket = new ServerSocket(1993).accept();
new AsyncTask<Void, Void, Void>() {
@Override
public Void doInBackground(Void... params) {
while (flag) {
try {
String line = new BufferedReader(new InputStreamReader(socket.getInputStream())).readLine();
Log.d("", line);
} catch (IOException ex) {
return null;
}
}
return null;
}
}.execute();
} catch (IOException ex) {
break;
}
}
You can convert your audio to byte array and write it into a output stream. Hope my answer will be useful.
I figured out the solution. The problem was actually with blocking Network I/O due to wrongly coded stream.
What I missed was
InputStream in = clientSoc.getInputStream();
DataInputStream DataIn =new DataInputStream(in)
while(DataIn!=null)
{
writeToFile(DataIn);
}
and client side too
OutputStream outToServer = client.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);
out.write(sData);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With