Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you write to a sockets input and output stream at the same time?

I have a Java application which is Voip. I am using the one socket to send and receive information at the same time via threads. Code is shown below ..

Socket clientSocket = sockList.accept();
OutputStream outSock = clientSocket.getOutputStream();
InputStream inSock = clientSocket.getInputStream();
new Thread( new Capture(outSock)).start();
new Thread( new PlayAudio(inSock)).start();
outSock.close();
clientSocket.close();

The problem that I'm finding is that when I write to the outputstream, it blocks on the first write. I'm sending not many bytes. Bellow is my write code.

private class Capture implements Runnable{

    private OutputStream out;
    public Capture(OutputStream out){
        this.out = out;
    }
    @Override
    public void run() {
        try{
            int numBytesRead;
            TargetDataLine outLine = getMic();
            outLine.open();
            outLine.start();

            byte[] data = new byte[outLine.getBufferSize() / 5];
            byte[] test = {0x1,0x1,0x1};

            while(true) {       
                //numBytesRead =  outLine.read(data, 0, data.length);
                //System.out.println(numBytesRead);
                out.write(test, 0, test.length);
                out.flush();
                /*if(numBytesRead > 0){
                    out.write(data, 0, data.length);
                    System.out.println("C");
                }*/
            }
        }catch(Exception ex){}
    }
}

The other thread that reads the sound code is ...

private class PlayAudio implements Runnable{

    private InputStream in;
    public PlayAudio(InputStream in){
        this.in = in;
    }
    @Override
    public void run() {
        int write;
        try{
        SourceDataLine inLine = getSpeaker();
        inLine.open();
        inLine.start();
        byte[] data = new byte[inLine.getBufferSize()];
        byte[] test = new byte[3];
        while(true){
            System.out.println(1);
            //write = in.read(data, 0, data.length);
            in.read(test, 0 , test.length);
            System.out.println(2);
            /*if(write > 0){
                inLine.write(data, 0, write);
                System.out.println(3);
                System.out.println(write);
            }*/
        }
        } catch(Exception ex){}
    }

}

I've commented a good portion of the actual code since I'm just trying to get it to work. My write function blocks indefinitely on the first write. Is it possible this could be a problem with my threads? My only thought is that the output and input streams are sharing my socket object which may cause a deadlock or something. Please let me know whats up.

like image 753
Dr.Knowitall Avatar asked Jan 24 '13 05:01

Dr.Knowitall


People also ask

Can you read and write from the same server socket?

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 ...

Which methods are used to read from and write to socket stream?

The EchoClient example creates a socket, thereby getting a connection to the echo server. It reads input from the user on the standard input stream, and then forwards that text to the echo server by writing the text to the socket. The server echoes the input back through the socket to the client.

What is an input stream used for in a socket connection?

Once our socket instance is connected to the server we can start obtaining input and output streams to the sever. Input streams are used to read data from the server while output streams are used to write data to the server.


2 Answers

Yes you can write on socket while reading , but you have to read socket in an independent thread. I am using this concept. Here the example is (read carefully it supports mutiple client as well ) :

public class TeacherServerSocket {

private Logger logger = Logger.getLogger(TeacherServerSocket.class);
public static Map<String, TeacherServerThread> connectedTeacher = new HashMap<String, TeacherServerThread>();
ServerSocket serverSocket;;

@Override
public void run() {
    // starting teacher server socket
    this.serverSocket = startServer();
    // if unable to to start then serverSocket would have null value
    if (null != this.serverSocket) {

        while (true) {
             //listening to client for infinite time
            Socket socket = listenToClient();
            if (null != socket) {

                TeacherServerThread teacherServerThread = new TeacherServerThread(socket);
                Thread thread = new Thread(teacherServerThread);
                thread.start();

                //putting teacher ip address and teacher object into map
                connectedTeacher.put(teacherServerThread.getTeacherIp(),teacherServerThread);
                System.out.println("INFO: Teacher is connected with address "+ teacherServerThread.getTeacherIp());

            }

        }


    }

}

@Override
public ServerSocket startServer() {
     //port number on which teacher server will  be run.
     int port=12345;

    try {
        // throw an exception if unable to bind at given port
        ServerSocket serverSocket = new ServerSocket(port);
        System.out.println("Teacher server socket started on port no :"+port);
        return serverSocket;

    } catch (IOException e) {

        logger.error("Unable to start Teacher Server socket");
        e.printStackTrace();

    }

    return null;

}

@Override

public Socket listenToClient() {

    if (this.serverSocket != null) {

        try {
            // throw an exception is unable to open socket
            Socket socket = this.serverSocket.accept();
            return socket;

        } catch (IOException e) {

            logger.error("Unable to open socket for teacher");
            e.printStackTrace();

        }
    } 
    else {

        logger.error("TeacherServerSocket has got null value please restart the server");

    }

    return null;
}





@Override
public Map getConnectedDevicesMap() {

return  TeacherServerSocket.connectedTeacher;

}

/**
 * This method will send message to connected teacher which comes form  student
 * @author rajeev
 * @param   message, which comes form student
 * @return  void
 *   * */
@Override
public void publishMessageToClient(String message) {
    if(TeacherServerSocket.connectedTeacher.size()>0){
        System.out.println("Total Connected Teacher: "+TeacherServerSocket.connectedTeacher.size());
        for (String teacherIp : TeacherServerSocket.connectedTeacher.keySet()) {

            TeacherServerThread teacherServerThread=TeacherServerSocket.connectedTeacher.get(teacherIp);
            teacherServerThread.publishMessageToTeacher(message);

        }
    }

}



@Override
public void stopServer() {

    if (this.serverSocket != null) {

        try {

            serverSocket.close();

        } catch (Exception e) {

            e.printStackTrace();

        }
    }

}


}

To read in an in independent thread for multiple client :

public class TeacherServerThread implements Runnable {


Logger logger=Logger.getLogger(TeacherServerThread.class);
Socket socket;
String teacherIp;

public TeacherServerThread(Socket socket) {
 this.socket=socket;
 this.teacherIp=socket.getInetAddress().toString();
}


@Override
public void run() {
    //starting reading
    ReadFromTeacherAndPublishToStudent messageReader=new ReadFromTeacherAndPublishToStudent();
    Thread thread=new Thread(messageReader);
    thread.start();
}





private class ReadFromTeacherAndPublishToStudent implements Runnable {

    @Override
    public void run() {
        String message=null;
        try {
            BufferedReader readTeacherData=new BufferedReader(new InputStreamReader(socket.getInputStream()));

            StudentServerSocket studentServerSocket=new StudentServerSocket();
            //sending message to student which is read by teacher
            while((message=readTeacherData.readLine())!=null){
                //System.out.println("Message found : "+message);
               //  studentServerSocket.publishMessageToClient(message); // do more stuff here 

            }
            // if message has null value then it mean socket is disconnected.
      System.out.println("INFO: Teacher with IP address : "+teacherIp+" is disconnected");
      TeacherServerScoket.connectedTeacher.remove(getTeacherIp());
        if(null!=socket){
            socket.close();
        }

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }




}

} //class



public void publishMessageToTeacher(String message){

    if(this.socket!=null){

        try {

        PrintWriter writeMessageToTeacher=new PrintWriter(this.socket.getOutputStream());
        writeMessageToTeacher.println(message);
        writeMessageToTeacher.flush();
        System.out.println(" Message published to teacher"+message);
        }catch(Exception e){
        logger.error(e.toString());
        logger.error("Exception In writing data to teacher");

        }


    }else {
        logger.error("Unable to publish message to teacher .Socket has Null value in publishMessageToTeacher");     
        System.out.println("ERROR: socket has null value can not publish to teacher");
    }



}

public String getTeacherIp()
{
    return teacherIp;

}
}

change code according to you requirement......

like image 84
Rajeev Avatar answered Oct 24 '22 10:10

Rajeev


Yes you can write to a sockets input and output stream at the same time.

from do-java-sockets-support-full-duplex

Since the input stream and the output stream are separate objects within the Socket, the only thing you might concern yourself with is, what happens if you had 2 threads trying to read or write (two threads, same input/output stream) at the same time? The read/write methods of the InputStream/OutputStream classes are not synchronized. It is possible, however, that if you're using a sub-class of InputStream/OutputStream, that the reading/writing methods you're calling are synchronized. You can check the javadoc for whatever class/methods you're calling, and find that out pretty quick.

like image 25
Sumit Singh Avatar answered Oct 24 '22 10:10

Sumit Singh