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