12

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.

4

3 に答える 3

19

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.

于 2013-01-24T05:14:45.413 に答える
5

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

于 2013-01-24T05:31:22.603 に答える
0

The reason it seems my write() is blocking is because I stupidly closed the Socket() and my input streams didn't realize it. Hence, no data is ever sent out. Silly error on my behalf.

于 2013-01-24T07:27:02.893 に答える