I have a socket client that hangs whenever I try to read the input stream from the socket.
DataInputStream dis = new DataInputStream(socket.getInputStream());
int singleByte;
while((singleByte = dis.read()) != -1) { //<-- hangs here
char c = (char)singleByte;
// append character
message_string += c;
}
Hangs on while((singleByte = dis.read()) != -1) {
I have confirmed that the server is echoing back what I send it in raw ASCII.
What am I not understanding? Why is it hanging when trying to read the server response?
Server side (handles the request):
class HandleInputBuffer implements Runnable {
private String msg = "";
private String response = "8";
public HandleInputBuffer(String str) {
this.msg = str;
}
#Override
public void run() {
String exception_msg = "";
// process incoming message
try {
if(msg!=null){
if(msg.length()>0){
// create and send reply
String response = "8";
// ****************************
// create and send response
// ****************************
try {
response = msg;
output_stream = new DataOutputStream(client_socket.getOutputStream());
output_stream.writeInt(response.getBytes("US-ASCII").length);
output_stream.write(response.getBytes("US-ASCII"));
output_stream.flush();
output_stream.close();
//client_socket.shutdownOutput();
client_socket.close();
} catch (IOException e) {
e.printStackTrace();
try{output_stream.flush();} catch (IOException e1) {}
try {client_socket.close();} catch (IOException e1) {}
try {updateConversationHandler = new Handler();} catch (Exception e1) {}
return;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Client side refactor - This code hangs int length = dis.readInt();
InetAddress serverAddr = InetAddress.getByName(edit_ip_address.getText().toString());
if(socket == null){
socket = new Socket(serverAddr, Integer.parseInt(edit_port.getText().toString()));
}
// send bytes
output_stream = new DataOutputStream(socket.getOutputStream());
output_stream.write(command.getBytes("US-ASCII"));
DataInputStream dis = new DataInputStream(socket.getInputStream());
int length = dis.readInt();
byte[] buffer = new byte[length]; //<-- OutOfMemoryException
dis.readFully(buffer);
for (byte b:buffer){
char c = (char)b;
message_string += c;
}
This loop will block until the peer closes the connection.
Ergo the peer is not closing the connection.
EDIT The correct way to read what you're sending is as follows:
You need to read the integer length word that you're writing. It doesn't magically appear via available():
int length = dis.readInt();
byte[] buffer = new byte[length];
dis.readFully(buffer);
But I would throw the sending and receiving code away and use readUTF()/writeUTF(), assuming the data is character data. If it isn't, you shouldn't be assembling it as a String.
EDIT 2 Proof that this works:
Client.java:
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
public class Client
{
public static void main(String[] args) throws IOException
{
try (Socket s = new Socket("localhost", 9999))
{
DataOutputStream out = new DataOutputStream(s.getOutputStream());
out.writeInt(1);
out.writeBytes("8");
DataInputStream in = new DataInputStream(s.getInputStream());
int count = in.readInt();
System.out.println("Reading "+count+" bytes");
byte[] buffer = new byte[count];
in.readFully(buffer);
System.out.write(buffer, 0, count);
System.out.println();
}
}
}
Server.java:
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Server
{
public static void main(String[] args) throws IOException
{
try (ServerSocket ss = new ServerSocket(9999))
{
try (Socket s = ss.accept())
{
DataInputStream in = new DataInputStream(s.getInputStream());
int count = in.readInt();
System.out.println("Reading "+count+" bytes");
byte[] buffer = new byte[count];
in.readFully(buffer);
System.out.write(buffer, 0, count);
System.out.println();
DataOutputStream out = new DataOutputStream(s.getOutputStream());
out.writeInt(count);
out.write(buffer, 0, count);
}
}
}
}
If yours doesn't, you are reading something else from the socket, or writing something else to it, or not running the code you think you're running.
Related
MyServer.java
import java.io.*;
import java.net.*;
public class MyServer {
public static void main(String[] args){
try{
ServerSocket ss=new ServerSocket(5001);
Socket s=ss.accept();//establishes connection
DataInputStream dis=new DataInputStream(s.getInputStream());
String str=(String)dis.readUTF();
System.out.println("message= "+str);
DataOutputStream dout=new DataOutputStream(s.getOutputStream());
if ("Hi".equals(str)){
dout.writeUTF("How are you?");
} else if ("Bye".equals(str)){
dout.writeUTF("Thankyou! Have a Good day!");
} **else if (str != null)){
try {
String numbers;
numbers = str.replaceAll("[^0-9]", "");
int number = Integer.parseInt(numbers);
dout.writeUTF("The line is being printed");
for (int i = 0; i < number; i++) {
dout.writeUTF(str.replaceAll("[^a-z,^A-Z]", ""));
}
} catch (Exception e) {
//TODO: handle exception
}**
} else {
dout.writeUTF("Sorry!");
}
dout.flush();
dout.close();
s.close();
ss.close();
} catch(Exception e) {
System.out.println(e);
}
}
}
MyClient.java
import java.io.*;
import java.net.*;
import java.util.*;
public class MyClient {
public static void main(String[] args) {
try{
Scanner sc = new Scanner(System.in);
Socket s=new Socket("localhost",5001);
DataOutputStream dout=new DataOutputStream(s.getOutputStream());
String str1= sc.nextLine();
dout.writeUTF(str1);
dout.flush();
DataInputStream dis=new DataInputStream(s.getInputStream());
String str=(String)dis.readUTF();
System.out.println("message= "+str);
dout.close();
dis.close();
s.close();
} catch(Exception e) {
System.out.println(e);}
}
}
I am giving input to the server from the client-side and want that input to be printed given a number of times on the client-side. But not able to do that. Can anyone let me know what mistake I am making here? It is replying to message "Hi" and "Bye", everything else is working fine.
The following is your code with my corrections.
(Notes after the code.)
Class MyServer
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class MyServer {
public static void main(String[] args) {
try (ServerSocket ss = new ServerSocket(5001)) {
Socket s = ss.accept();// establishes connection
InputStream is = s.getInputStream();
DataInputStream dis = new DataInputStream(is);
String str = dis.readUTF();
System.out.println("message= " + str);
DataOutputStream dout = new DataOutputStream(s.getOutputStream());
if ("Hi".equals(str.trim())) {
dout.writeUTF("How are you?");
}
else if ("Bye".equals(str)) {
dout.writeUTF("Thankyou! Have a Good day!");
}
else if (str != null) {
try {
String numbers;
numbers = str.replaceAll("[^0-9]", "");
int number = Integer.parseInt(numbers);
dout.writeUTF("The line is being printed");
for (int i = 0; i < number; i++) {
dout.writeUTF(str.replaceAll("[^a-z,^A-Z]", ""));
}
}
catch (Exception e) {
e.printStackTrace();
}
}
dout.writeUTF("END");
dout.flush();
}
catch (Exception e) {
e.printStackTrace();
}
try {
Thread.sleep(2000L);
}
catch (InterruptedException xInterrupted) {
// Ignore.
}
}
}
Class MyClient
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.net.Socket;
import java.util.Scanner;
public class MyClient {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String str1 = sc.nextLine();
try (Socket s = new Socket("localhost", 5001)) {
DataOutputStream dout = new DataOutputStream(s.getOutputStream());
dout.writeUTF(str1);
dout.flush();
InputStream is = s.getInputStream();
DataInputStream dis = new DataInputStream(is);
String str = dis.readUTF();
while (!"END".equals(str)) {
System.out.println("message= " + str);
str = dis.readUTF();
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
Sending and receiving data via sockets is not instantaneous. Method readUTF will wait until there is data to read. It will read all the data sent in the last invocation of method writeUTF. Method readUTF will wait indefinitely. Hence the server needs to send notification to the client that there is no more data to send. In the above code I send the string END to indicate the end of the data that the server is sending. Note also that you only need to close resources that you explicitly create. In class MyServer, this means ServerSocket only. I use try-with-resources to ensure that ServerSocket is closed.
Similarly, in class MyClient, the only resource that needs to be explicitly closed is the Socket – which I again do using try-with-resources.
If the server terminates, the socket is closed. Hence, in class MyServer, after sending data to the client, the server waits for two seconds which is hopefully enough time for the client to read that data.
I have written a simple NIO Server and Inner-Client (Inside the same program)in a single program such that Server receives data from outside and the Inner-Client sends the data received by the server to out side Server. I am running both the processes continuously in two parallel threads using While() loops. Now the problem is, I will be receiving data at a very high speed to the Inside server and everything I receive, I will send them to the outer server using the Inside client. Some times, the retrieval of the data from the Buffer resulting in half the size of the total string. That means I am receiving "HELLO", but the total string is "HELLO SERVER". This is just an example. I will receive very long strings. Similarly, after sending the data to Outer-server through Inner client I will be listening for data and I am receiving the same half-strings.Is there any way I can eliminate these Half-strings and get the full-length string. I have to get the full string without any fail.
I am using while loops for the process. This is making the CPU utilization go high like 50%. Is there any way I can reduce the CPU utilization without using Thread.sleep method? Because I need to continuously listen to data from the Outer parties. They may send 2-4 strings for one single request. I tried using Executor service thread for running the processes continuously but it requires some sleep to be included. If I include some sleep I am not able to get the String and if I don't include the sleep my CPU-Utilization is going very high (50-60%). Can anyone help me with these two issues?
Here is my code:
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.StandardSocketOptions;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class Main {
static SocketChannel channel;
public static void main(String[] args) throws IOException {
System.out.println("Listening for connections on : 8888"); //8888
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.bind(new InetSocketAddress(8888));
channel = serverChannel.accept();
System.out.println("Connected...");
channel.setOption(StandardSocketOptions.TCP_NODELAY, true);
channel.configureBlocking(false);
ReceiveFromOMS receivefromOMS;
SendToExchange sendExchange;
receivefromOMS = new ReceiveFromOMS();
sendExchange = new SendToExchange();
Thread t1 = new Thread(receivefromOMS);
Thread t2 = new Thread(sendExchange);
t1.start();
t2.start();
}
}
class ReceiveFromOMS extends Thread{
public static SocketChannel channel;
static ByteBuffer buffer = ByteBuffer.allocate(1024);
static ServerSocketChannel serverChannel ;
public static int ReceiveFromOMSPort;
BlockingQueue<String> fromOMSqueue = new LinkedBlockingQueue<>(30);
#Override
public void run(){
while(true){
try {
receiveFromOMS();
} catch (InterruptedException ex) {
System.err.println(ex.getMessage());
try {
Thread.sleep(5000);
} catch (InterruptedException ex1) { }
}
}
}
public void receiveFromOMS() throws InterruptedException{
try {
int numRead = -1;
numRead = channel.read(buffer);
while(numRead==0){
numRead = channel.read(buffer);
}
if (numRead == -1) {
Socket socket = channel.socket();
SocketAddress remoteAddr = socket.getRemoteSocketAddress();
System.out.println("Connection closed by client: " + remoteAddr);
channel.close();
return;
}
byte[] data = new byte[numRead];
System.arraycopy(buffer.array(), 0, data, 0, numRead);
fromOMSqueue.add(new String(data));
String msg = fromOMSqueue.poll();
System.out.println("OutGoing To Exchange>> " + msg);
SendToExchange.sendToEchange(msg);
buffer.flip();
buffer.clear();
} catch (IOException ex) {
System.err.println(ex.getMessage());
Thread.sleep(5000);
}
}
}
class SendToExchange extends Thread{
static SocketChannel channel;
static ByteBuffer bb = ByteBuffer.allocateDirect(1024);
static Charset charset = Charset.forName("UTF-8");
public byte[] data;
public static String message;
#Override
public void run(){
try {
while(true){
receive();
Thread.sleep(100);
}
} catch (IOException | InterruptedException ex) {
System.err.println(ex.getMessage());
try {
Thread.sleep(5000);
} catch (InterruptedException ex1) {}
}
}
public static void sendToEchange(String msg){
try {
bb = stringToByteBuffer(msg, charset);
channel.write(bb);
} catch (IOException ex) {
System.err.println(ex.getMessage());
}
}
public void receive() throws IOException {
ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
int numRead = -1;
numRead = channel.read(buffer);
while (numRead == 0) {
numRead = channel.read(buffer);
}
if (numRead == -1) {
Socket socket = channel.socket();
SocketAddress remoteAddr = socket.getRemoteSocketAddress();
System.out.println("Connection closed by Exchange: " + remoteAddr);
channel.close();
return;
}
buffer.flip();
data = new byte[numRead];
buffer.get(data);
message = new String(data);
System.out.println("Incoming from Exchange>> " + message);
buffer.clear();
}
public static ByteBuffer stringToByteBuffer(String msg, Charset charset){
return ByteBuffer.wrap(msg.getBytes(charset));
}
}
Lets assume that your server is appending to each string an End of message marker string, e.g. "<EOM>", then the following modification of your code (treat it as a sketch since I did not verified it completely) can be used to wait for the full string:
String end = "<EOM>";
StringBuilder curStr = new StringBuilder();
int numRead = 0;
while(-1 != (numRead = channel.read(buffer))){
curStr.append(new String(buffer.array(), 0, numRead, Charset.forName("UTF-8")));
int endIdx = curStr.indexOf(end);
if (endIdx != -1) {
fromOMSqueue.add(curStr.substring(0, endIdx + end.length()));
break;
}
}
if (numRead == -1) {
Socket socket = channel.socket();
SocketAddress remoteAddr = socket.getRemoteSocketAddress();
System.out.println("Connection closed by client: " + remoteAddr);
channel.close();
return;
}
String msg = fromOMSqueue.poll();
i write a program client-server with multi threading for send - receive file. The program runs and client send and server receive. the files are created but empty new files are created
Why? please help me
class client :
import java.io.*;
import java.net.Socket;
public class Client extends Thread {
Socket socket = null;
Socket socket1 = null;
public void sendFile() throws IOException {
String host = "127.0.0.1";
String host1 = "127.0.0.2";
socket = new Socket(host, 1024);
socket1 = new Socket(host1, 1025);
File file = new File("/home/reza/Desktop/link help");
File file1 = new File("/home/reza/Desktop/hi");
long length = file.length();
long length1 = file1.length();
final byte[] bytes = new byte[(int) length];
final byte[] bytes1 = new byte[(int) length1];
FileInputStream fis = new FileInputStream(file);
FileInputStream fis1 = new FileInputStream(file1);
#SuppressWarnings("resource")
final BufferedInputStream bis = new BufferedInputStream(fis);
final BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream());
#SuppressWarnings("resource")
final BufferedInputStream bis1 = new BufferedInputStream(fis1);
final BufferedOutputStream out1 = new BufferedOutputStream(socket1.getOutputStream());
Thread t = new Thread(new Runnable() {
public void run()
{
while(socket.isConnected())
{
Wait2();
try {
System.out.println("ok");
int count;
while ((count = bis.read(bytes)) > 0) {
out.write(bytes, 0, count);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
Thread t1 = new Thread(new Runnable() {
public void run() {
while(socket1.isConnected())
{
Wait2();
try {
System.out.println("ok1");
int count1;
while ((count1 = bis1.read(bytes1)) > 0) {
out1.write(bytes1, 0, count1);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
t1.start();
t.start();
socket.close();
socket1.close();
}
public void Wait2()
{
try {
Thread.sleep(3000);
} catch (InterruptedException x) {
System.out.println("Interrupted!");
}
}
}
class server:
import java.io.*;
import java.net.*;
public class Server {
public Server()
{
Thread t = new Thread(new Client());
t.start();
Thread t1 = new Thread(new Client());
t1.start();
}
//#SuppressWarnings("null")
public void recivefile() throws IOException {
ServerSocket serverSocket = null;
ServerSocket serverSocket1 = null;
try {
serverSocket = new ServerSocket(1024);
} catch (IOException ex) {
System.out.println("Can't setup server on this port number. ");
}
try {
serverSocket1 = new ServerSocket(1025);
} catch (IOException ex) {
System.out.println("Can't setup server on this port number1. ");
}
Socket socket = null;
Socket socket1 = null;
InputStream is = null;
InputStream is1 = null;
FileOutputStream fos = null;
FileOutputStream fos1 = null;
BufferedOutputStream bos = null;
BufferedOutputStream bos1 = null;
int bufferSize = 0;
int bufferSize1 = 0;
try {
socket = serverSocket.accept();
socket1 = serverSocket1.accept();
} catch (IOException ex) {
System.out.println("Can't accept client connection. ");
}
try {
is = socket.getInputStream();
is1 = socket1.getInputStream();
bufferSize = socket.getReceiveBufferSize();
bufferSize1 = socket1.getReceiveBufferSize();
//bufferSize2 = socket2.getReceiveBufferSize();
System.out.println("Buffer size: " + bufferSize);
System.out.println("file recieved");
System.out.println("Buffer size1: " + bufferSize1);
System.out.println("file recieved");
System.out.println("file recieved");
} catch (IOException ex) {
System.out.println("Can't get socket input stream. ");
}
try {
fos = new FileOutputStream("/home/reza/Desktop/reza");
bos = new BufferedOutputStream(fos);
fos1 = new FileOutputStream("/home/reza/Desktop/ali");
bos1 = new BufferedOutputStream(fos1);
} catch (FileNotFoundException ex) {
System.out.println("File not found. ");
}
byte[] bytes = new byte[bufferSize];
int count;
while ((count = is.read(bytes)) > 0) {
bos.write(bytes, 0, count);
}
byte[] bytes1 = new byte[bufferSize1];
int count1;
while ((count1 = is1.read(bytes1)) > 0) {
bos1.write(bytes1, 0, count1);
}
bos.flush();
bos.close();
bos1.flush();
bos1.close();
is.close();
is1.close();
socket.close();
serverSocket.close();
socket1.close();
serverSocket1.close();
}
public static void main(String[] args) throws IOException
{
System.out.println("server is run, please send file");
Server s = new Server();
s.recivefile();
}
}
client test class:
import java.io.IOException;
public class clientTest extends Thread {
public static void main(String[] args) throws IOException, InterruptedException
{
Client client = new Client();
client.sendFile();
}
}
I believe this code in the server to be your issue:
while ((count = is.read(bytes)) > 0) {
bos.write(bytes, 0, count);
}
byte[] bytes1 = new byte[bufferSize1];
int count1;
while ((count1 = is1.read(bytes1)) > 0) {
bos1.write(bytes1, 0, count1);
}
bos.flush();
bos.close();
bos1.flush();
bos1.close();
is.close();
is1.close();
socket.close();
serverSocket.close();
socket1.close();
serverSocket1.close();
So the server has connected to the client, then it immediately checks to see if there are any bytes to read, if not it stops reading and closes the connection. If this happens faster than the client can deliver any bytes, boom, no data is received. And it WILL happend faster than the client can send data because the client is connecting THEN starting thread to send the data.
Instead, the server should read on each connection for as long as the client has maintained the connection alive. The server needs to wait for the data to be received.
Notice that in your code, the client is waiting for the server to close the connection. But how is the server supposed to know when all the data is sent? Either the client must close the connection or the client must send an EOF-type marker to the server indicating an end of the data and that it is safe to close the connection.
I am new to Java programming and I am trying to create a UDP server. When I compile the code it says it could not listen to port 4722 and I would like to know why. Below is the code. I would be grateful for any advice.
import java.net.*;
import java.io.*;
public class Server
{
public static void main(String[] args) throws IOException
{
DatagramSocket serverSocket = new DatagramSocket(4722);
Socket clientSocket = null;
byte[] receiveData = new byte[1024];
byte[] sendData = new byte [1024];
boolean command = true;
try
{
serverSocket = new DatagramSocket(4722);
DatagramPacket receivePacket = new DatagramPacket(receiveData,receiveData.length);
System.out.println("Waiting for client...");
}
catch (IOException e)
{
System.err.println("Could not listen on port: 4722.");
System.exit(1);
}
DatagramPacket packet = new DatagramPacket (sendData,sendData.length,4722);
serverSocket.send(packet);
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String inputLine, outputLine;
mathematicalProtocol bbm = new mathematicalProtocol();
outputLine = bbm.processInput(null);
out.println(outputLine);
while ((inputLine = in.readLine()) != null)
{
if(inputLine.equals("Bye."))
break;
outputLine = bbm.processInput(inputLine);
out.println(outputLine);
if (outputLine.equals("Bye."))
break;
}
out.close();
in.close();
clientSocket.close();
serverSocket.close();
}
}
You are initializing serverSocket and then making a new DatagramSocket on the same port again (and you can't do that as it's already bound on the first DatagramSocket). I.e. remove the following line:
serverSocket = new DatagramSocket(4722);
Here is a complete example of client/server UDP communication.
The server read data from a file and send each line to the client.
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
/**
* #author nono
*
*/
public class UDPFileSender {
static class Client implements Runnable {
// Reception socket
private DatagramSocket socket;
// UDP packet to receive data into
private DatagramPacket packet;
// Flag for initialisation
private boolean failedInit = true;
/**
* Client constructor.
* #param receptionPort
* #param packetMaxLenght
*/
public Client(int receptionPort, int packetMaxLenght) {
try {
// Create the socket using the reception port
this.socket = new DatagramSocket(receptionPort);
// Init the packet
this.packet = new DatagramPacket(new byte[packetMaxLenght],packetMaxLenght);
this.failedInit = false;
} catch (SocketException e) {
//Port already used or other error
e.printStackTrace();
}
}
#Override
public void run() {
if(failedInit){
return;
}
// Loop undefinitly
while(true){
try {
System.out.println("Waiting for packet...");
// Wait for packet
socket.receive(packet);
// Assuming you are receiving string
String msg = new String(packet.getData());
System.out.println("Received : " + msg);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
try {
int port = 4722;
//Start a client that can listen
new Thread(new Client(port,1024)).start();
// Creaete a reader
BufferedReader reader = new BufferedReader(new FileReader("File.txt"));
//Create a socket
DatagramSocket socket = new DatagramSocket();
// Create a packet
byte[] data = new byte[1024]; // Max length
DatagramPacket packet = new DatagramPacket(data, data.length);
// Set the destination host and port
packet.setAddress(InetAddress.getByName("localhost"));
packet.setPort(port);
String line = null;
while((line = reader.readLine()) != null){
//Set the data
packet.setData(line.getBytes());
//Send the packet using the socket
System.out.println("Sending : " + line);
socket.send(packet);
Thread.sleep(200);
}
//Close socket and file
reader.close();
socket.close();
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
If your file contains :
Hello
World
You should see :
Waiting for packet...
Sending : Hello
Received : HelloWaiting for packet...
Sending : World
Received : World
Waiting for packet...
I am trying to write a Java voice chat application, and have achieved echo capabilities, but when trying to connect multiple clients, I am stuck. I understand that you cannot iterate through sockets and send the data to everyone connected without mixing-down the data. (I have tried and it sounds nothing like how it should). I am not quite sure what to do, and I am using a very simple byte-buffered echo server as the server (where I would like to perform the mixdown). I also have a client that takes microphone input, sends it to the server, takes data from the server, and plays that data out of a speaker.
NOTE: The client is composed of 2 classes (Program and SoundReceiver). I am using the javax.sound.sampled library.
Echo Server: http://pastebin.com/c9KiaTpJ
import java.net.*;
import java.io.*;
import java.util.*;
public class Echo
{
public static void main(String[] args) throws Exception
{
ServerSocket serverSocket = new ServerSocket(3000);
while(true){Thread echoThread = new Thread(new EchoThread(serverSocket.accept()));
echoThread.start();}
}
}
class EchoThread implements Runnable
{
public static Collection<Socket> sockets = new ArrayList<Socket>();
Socket connection = null;
DataInputStream dataIn = null;
DataOutputStream dataOut = null;
public EchoThread(Socket conn) throws Exception
{
connection = conn;
dataIn = new DataInputStream(connection.getInputStream());
dataOut = new DataOutputStream(connection.getOutputStream());
sockets.add(connection);
}
public void run()
{
int bytesRead = 0;
byte[] inBytes = new byte[1];
while(bytesRead != -1)
{
try{bytesRead = dataIn.read(inBytes, 0, inBytes.length);}catch (IOException e){}
if(bytesRead >= 0)
{
sendToAll(inBytes, bytesRead);
}
}
sockets.remove(connection);
}
public static void sendToAll(byte[] byteArray, int q)
{
Iterator<Socket> sockIt = sockets.iterator();
while(sockIt.hasNext())
{
Socket temp = sockIt.next();
DataOutputStream tempOut = null;
try
{
tempOut = new DataOutputStream(temp.getOutputStream());
} catch (IOException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}
try{tempOut.write(byteArray, 0, q);}catch (IOException e){}
}
}
}
Client Program Class: http://pastebin.com/v24CYwXE
import java.io.DataOutputStream;
import java.net.*;
import javax.sound.sampled.*;
public class Program
{
public static void main(String[] args) throws Exception
{
AudioFormat af = new AudioFormat(8000.0f,8,1,true,false);
DataLine.Info info = new DataLine.Info(TargetDataLine.class, af);
TargetDataLine microphone = (TargetDataLine)AudioSystem.getLine(info);
microphone.open(af);
Socket conn = new Socket("localhost",3000);
microphone.start();
DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
int bytesRead = 0;
byte[] soundData = new byte[1];
Thread inThread = new Thread(new SoundReceiver(conn));
inThread.start();
while(bytesRead != -1)
{
bytesRead = microphone.read(soundData, 0, soundData.length);
if(bytesRead >= 0)
{
dos.write(soundData, 0, bytesRead);
}
}
System.out.println("IT IS DONE.");
}
}
Client SoundReceiver Class: http://pastebin.com/2tt0Jucv
import java.net.*;
import java.io.*;
import javax.sound.sampled.*;
public class SoundReceiver implements Runnable
{
Socket connection = null;
DataInputStream soundIn = null;
SourceDataLine inSpeaker = null;
public SoundReceiver(Socket conn) throws Exception
{
connection = conn;
soundIn = new DataInputStream(connection.getInputStream());
AudioFormat af = new AudioFormat(8000.0f,8,1,true,false);
DataLine.Info info = new DataLine.Info(SourceDataLine.class, af);
inSpeaker = (SourceDataLine)AudioSystem.getLine(info);
inSpeaker.open(af);
}
public void run()
{
int bytesRead = 0;
byte[] inSound = new byte[1];
inSpeaker.start();
while(bytesRead != -1)
{
try{bytesRead = soundIn.read(inSound, 0, inSound.length);} catch (Exception e){}
if(bytesRead >= 0)
{
inSpeaker.write(inSound, 0, bytesRead);
}
}
}
}
Basically, I'd like to merge all incoming bytes into one byte array while keeping everyone's voice full (just like a 3-way phone call).
setting the limit to the serverSocket may help, eg new ServerSocket(3000,101); something like backlog or queue length..
It's this line:
try
{
tempOut.write(byteArray, 0, q);
}
catch (IOException e){
}
in server side which i think sends the data back to the client due which there is an echo. I think you should omit the line.
I think you need to create a check in the server side. its like if sendAll is being called from EChoThread that has connection instance just pass this to sendAll and there compare sockIt with connection if they are the same then this is the same socket that is sending the date and there is no need to send data to it self so just skip it and move to the next socket.
the following changes should be made at server side:
public void run()
{
int bytesRead = 0;
byte[] inBytes = new byte[1];
while(bytesRead != -1)
{
try{bytesRead = dataIn.read(inBytes, 0, inBytes.length);}catch (IOException e) {}
if(bytesRead >= 0)
{
sendToAll(connection, inBytes, bytesRead);
}
}
sockets.remove(connection);
}
public static void sendToAll(Socket connection, byte[] byteArray, int q)
{
Iterator<socket> sockIt = sockets.iterator();
while(sockIt.hasNext())
{
Socket temp = sockIt.next();
if(connection == temp){
continue;
}
DataOutputStream tempOut = null;
try
{
tempOut = new DataOutputStream(temp.getOutputStream());
} catch (IOException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}
try{tempOut.write(byteArray, 0, q);}catch (IOException e){}
}
}
public void run()
{
int bytesRead = 0;
byte[] inBytes = new byte[1];
while(bytesRead != -1)
{
try{bytesRead = dataIn.read(inBytes, 0, inBytes.length);}catch (IOException e) {}
if(bytesRead >= 0)
{
sendToAll(connection, inBytes, bytesRead);
}
}
sockets.remove(connection);
}
public static void sendToAll(Socket connection, byte[] byteArray, int q)
{
Iterator<socket> sockIt = sockets.iterator();
while(sockIt.hasNext())
{
Socket temp = sockIt.next();
if(connection == temp){
continue;
}
DataOutputStream tempOut = null;
try
{
tempOut = new DataOutputStream(temp.getOutputStream());
} catch (IOException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}
try{tempOut.write(byteArray, 0, q);}catch (IOException e){}
}
}