Passing multiple objects from children to main thread - java

i've this problem, I've a Multithreaded server running. here it's the code:
ServerSocket serverSocket=null; // defining a server socket to listen data
Socket clientSocket = null; // defining a client socket to send data
final int port=8080;
int i=0;
try {
serverSocket = new ServerSocket(port); // Opening a server socket to listen for client calls
System.out.println("Server started.");
} catch (Exception e) {
System.err.println("Port already in use.");
System.exit(1);
}
while (true) {
try {
clientSocket = serverSocket.accept(); //binding server socket to client socket incoming call and accepting call
System.out.println("Accepted connection : " + clientSocket);
i=i+1;
Thread t = new Thread(new newClientHandler(clientSocket, NodePRs[1]),"thread"+i); //Create a new thread to handle the single call coming from one client
System.out.println("Thread "+t.getName()+" is starting");
t.start(); //Starting the run method contained in newCLIENTHandler class
} catch (Exception e) {
System.err.println("Error in connection attempt.");
}
}//end while
All that i need is to let the children thread (opened every time a client request come) pass (like a function return) 4 variables when the children thread die. The newClientHandler code is this:
public class newClientHandler implements Runnable {
private final static int FILE_SIZE=6022386;
private Socket clientSocket;
private PaillierPrivateKey PrivKey;
ServerSocket servSock;
BigInteger[] msg = null;
BigInteger preamble = null;
int bytesRead;
int current = 0;
DataOutputStream dos = null;
BufferedReader dis = null;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
int msgtype=-1;
int num_of_rx_cnks=-1;
public newClientHandler(Socket client, PaillierPrivateKey PR) {
this.clientSocket = client;
this.PrivKey = PR;
}
//I CAN RECEIVE 3 TYPES OF MESSAGES: SHARE, THE ENCRYPTED PASSWORD, THE 4 PDMS
public void run() {
try{
ObjectOutputStream oos = new ObjectOutputStream(clientSocket.getOutputStream());
ObjectInputStream ois = new ObjectInputStream(clientSocket.getInputStream());
preamble = (BigInteger) ois.readObject();
System.out.println("Received Preamble is:"+preamble);
oos.writeObject("Received preamble");
msg =(BigInteger[]) ois.readObject();
System.out.println("Received Message is:"+msg+"\n"+msg[0]+"\n"+msg[2]);
String sPlain = Utilities.bigIntegerToString(preamble);
String[] splitArr=Pattern.compile("-").split(sPlain);
msgtype=Integer.parseInt(splitArr[0]);
num_of_rx_cnks=Integer.parseInt(splitArr[1]);
System.out.println("Message type: "+msgtype+"\n"+"Number of received cnks: "+num_of_rx_cnks);
//a questo punto ho i miei 29 biginteger. Li devo sistemare uno accanto all'altro e rimettere nel file.
switch(msgtype){
case 1: //Share received
System.out.println("Received the share");
for(int i=0;i<num_of_rx_cnks;i++){
String name = new String();
if(i<9){
name="Cyph2"+".00"+(i+1);
}
if(i>8){
name="Cyph2"+".0"+(i+1);
}
Utilities.newBigIntegerToFile(msg[i], name);
}
Utilities.retrieveShare(PrivKey, 2,"myShare");
int l, w;
BigInteger v, n, shares, combineSharesConstant;
BigInteger[] viarray=new BigInteger[5];
PaillierPrivateThresholdKey[] res = null;
try {
FileReader File= new FileReader("myShare");
BufferedReader buf=new BufferedReader(File);
String line=buf.readLine();
l = Integer.parseInt(line.split(":")[1]);
line = buf.readLine();
w = Integer.parseInt(line.split(":")[1]);
line = buf.readLine();
v = new BigInteger(line.split(":")[1]);
line = buf.readLine();
n = new BigInteger(line.split(":")[1]);
line = buf.readLine();
combineSharesConstant = new BigInteger(line.split(":")[1]);
line = buf.readLine();
shares = new BigInteger(line.split(":")[1]);
for(int i=0; i<5; i++){
line = buf.readLine();
viarray[i] = BigInteger.ZERO;
}
SecureRandom rnd = new SecureRandom();
PaillierPrivateThresholdKey result = new PaillierPrivateThresholdKey(n, l, combineSharesConstant, w, v,
viarray, shares, 2, rnd.nextLong());//il 2 qua รจ il nodeID
}catch(IOException e){
System.out.println(e);
}
break;
case 2: // Session Secret received
break;
case 3: //PDM received
break;
}//end switch
}catch(IOException ioe){
System.out.println(ioe);
}catch(ClassNotFoundException cnfe){
System.out.println(cnfe);
}finally {
try{
if (dis != null) dis.close();
if (dos != null) dos.close();
if (clientSocket!=null) clientSocket.close();
}catch (IOException e){
System.out.println(e);
}
}
}
}
I'd like to pass l, w, v, n and so on to let my main thread do some processing. How can i modify my code to do it?

Use a Callable instead of a Runnable.
Bundle the 4 variables into a class and implement Callable<YourNewClass>. Run your callable with an executor and you'll get the results in a Future<YourNewClass>.

Related

exchange both string and binary data using socket without closing it

i'm working on an instant messaging project which it's client side is android and server is java
i need to use socket with streams
here is my protocol (something like HTTP) :
Method : attachment \n
Content-Length : {some-int-value} \n
\r\n
binary data bla bla bla...
lets assume i want to send this message from client to server
by doing so exchanging header section goes pretty well
but reading binary data at the server side never complete and server goes into hang for good
Client side code :
Socket socket = new Socket();
SocketAddress address = new InetSocketAddress(SERVER_ADDRESS, SERVER_PORT);
try {
socket.connect(address);
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"));
byte[] data = getSomeBinaryData();
writer.write("Method : attachment" + "\n");
writer.write("Content-Length : " + data.length + "\n");
writer.write("\r\n");
writer.flush();
out.write(data); // write binary data
// do more exchange later
} catch (IOException ex) {
// handle exception
}
Server starter code :
public static void main(String[] args){
ExecutorService pool = Executors.newFixedThreadPool(50);
try (ServerSocket server = new ServerSocket(PORT_NUMBER)) {
while (true) {
try {
Socket connection = server.accept();
Callable<Void> task = new ClientTask(connection);
pool.submit(task);
} catch (IOException ex) {}
}
} catch (IOException ex) {
System.err.println("Couldn't start server");
}
}
Server Task thread for each client :
class ClientTask implements Callable<Void> {
private Socket connection;
private HashMap<String, String> header = new HashMap<>();
private byte[] content;
ClientTask(Socket c) {
this.connection = c;
}
#Override
public Void call() throws Exception {
InputStream in = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
readHeader(reader);
System.out.println("incoming message : " + header.get("Method"));
int contentLength = Integer.parseInt(header.get("Content-Length"));
content = new byte[contentLength];
int bytesRead = in.read(content, 0, contentLength);
System.out.print(bytesRead);
return null;
}
private void readHeader(BufferedReader reader){
try {
char c;
StringBuilder builder = new StringBuilder();
while ((c = (char) reader.read()) != '\r'){
if(c == '\n'){
String line = builder.toString();
line = line.replaceAll(" ", "");
String[] sections = line.split(":");
header.put(sections[0], sections[1]);
builder = new StringBuilder(); // clear builder
}else {
builder.append(c);
}
}
reader.read(); // skip the last \n character after header
} catch (IOException e) {
e.printStackTrace();
}
}
As James said a clue I wanted to share the solution
maybe it help someone with similar issue
in the call method of ClientTask class i should use this code :
#Override
public Void call() throws Exception {
InputStream in = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
readHeader(reader);
System.out.println("incoming message : " + header.get("Method"));
// read binary Content
int bytesRead = 0;
int bytesToRead = Integer.parseInt(header.get("Content-Length"));
content = new byte[bytesToRead];
while (bytesRead < bytesToRead) {
int result = in.read(content, bytesRead, bytesToRead - bytesRead);
if (result == -1)
break; // end of stream
bytesRead += result;
}
return null;
}

Java TCP file transfer data lost randomly [duplicate]

This question already has an answer here:
Java TCP server cannot receive message from more than one client
(1 answer)
Closed 5 years ago.
[Edit: This post has been marked as duplicate without reviewing properly. The two posts address completely different problem which the reviewer did not take time to carefully read.]
The server will connect to three instances of client. The server has three threads to receive requests from these three clients. Each of the three instances of client will have a ServerThread (the server requests for file or file list from this thread) and a UserThread (it will take user input and communicated with the server and receive file/file list depending on the user input).
Let's say client_0 wants a file that is in possession of client_1. When UserThread of client_0 requests the server for the file, the server communicates with ServerThread of client_1 and ServerThread of client_1 sends the byteArray of the file to the server. The server then sends the byteArray back to the UserThread of client_0 and client_0 then saves the byteArray as a file.
I am using the same type of code for the server to receive the bytearray from client_1 and for client_0 to receive the byteArray from the server. The server's code works perfectly everytime and receives the byteArrayperfectly but in client_0, the loop that receives the byteArray gets stuck at the last part of the file although the same type of loop is working perfectly in server. The variable position holds how much of the byteArray has been received and it doesn't reach the FILE_SIZE in the client_0 but does so in server without any problem. The System.out.println() statements confirm this.
In addition, this problem in client_0 is happening 90% of the time. In the other 10%, the loop in client_0 works just like it is supposed to! Why is this happening?
The codes are long but if anyone manages to go through and give some suggestion, it will be a great help.
Server:
package server;
import java.io.*;
import java.net.*;
public class Server {
public static void main(String[] args) throws Exception {
String[] id={"cp 1","cp 2","cp 3"}, pass={"123","456","789"};
ServerSocket welcome = new ServerSocket(6000), tmpSocket;
Socket STsocket, UTsocket;
int startSTport = 6001;
int startUTport = 6011;
// for ServerThread of client
BufferedReader STmsgFrom[] = new BufferedReader[3];
PrintWriter STmsgTo[] = new PrintWriter[3];
DataInputStream[] STfileFrom = new DataInputStream[3];
// for UserThread of client
BufferedReader UTmsgFrom[] = new BufferedReader[3];
PrintWriter UTmsgTo[] = new PrintWriter[3];
DataOutputStream[] UTfileTo = new DataOutputStream[3];
for(int i=0; i<3; i++) {
// connecting initially
System.out.println("Waiting for client "+i);
Socket client = welcome.accept();
PrintWriter send = new PrintWriter(client.getOutputStream(),true);
BufferedReader receive = new BufferedReader(new InputStreamReader(client.getInputStream()));
// sending serial number
send.println(Integer.toString(i));
// sending ports for thread sockets
send.println(Integer.toString(startSTport+i));
send.println(Integer.toString(startUTport+i));
// accepting sockets
tmpSocket = new ServerSocket(startSTport+i);
STsocket = tmpSocket.accept();
tmpSocket = new ServerSocket(startUTport+i);
UTsocket = tmpSocket.accept();
// creating communications
STmsgFrom[i] = new BufferedReader(new InputStreamReader(STsocket.getInputStream()));
STmsgTo[i] = new PrintWriter(STsocket.getOutputStream(),true);
STfileFrom[i] = new DataInputStream(STsocket.getInputStream());
UTmsgFrom[i] = new BufferedReader(new InputStreamReader(UTsocket.getInputStream()));
UTmsgTo[i] = new PrintWriter(UTsocket.getOutputStream(),true);
UTfileTo[i] = new DataOutputStream(UTsocket.getOutputStream());
System.out.println("Connected client "+i);
}
ClientThread ct0 = new ClientThread(0,STmsgFrom,STmsgTo,STfileFrom,UTmsgFrom,UTmsgTo,UTfileTo);
ClientThread ct1 = new ClientThread(1,STmsgFrom,STmsgTo,STfileFrom,UTmsgFrom,UTmsgTo,UTfileTo);
ClientThread ct2 = new ClientThread(2,STmsgFrom,STmsgTo,STfileFrom,UTmsgFrom,UTmsgTo,UTfileTo);
ct0.start();
ct1.start();
ct2.start();
System.out.println("Server Stup Complete!");
}
}
class ClientThread extends Thread {
String msg;
int cid;
BufferedReader[] STmsgFrom;
PrintWriter[] STmsgTo;
DataInputStream[] STfileFrom;
BufferedReader[] UTmsgFrom;
PrintWriter[] UTmsgTo;
DataOutputStream[] UTfileTo;
public ClientThread(int cid,BufferedReader[] STmsgFrom,PrintWriter[] STmsgTo,DataInputStream[] STfileFrom,BufferedReader[] UTmsgFrom,PrintWriter[] UTmsgTo,DataOutputStream[] UTfileTo) {
this.cid=cid;
this.STmsgFrom=STmsgFrom;
this.STmsgTo=STmsgTo;
this.STfileFrom = STfileFrom;
this.UTmsgFrom=UTmsgFrom;
this.UTmsgTo=UTmsgTo;
this.UTfileTo = UTfileTo;
}
#Override
public void run() {
while(true) {
try {
// receiving request from receiver UserThread
msg = UTmsgFrom[cid].readLine();
if(msg.equals("get list")) { // receiver requested for file list
System.out.println("Request from "+cid+": "+msg);
for(int i=0; i<3; i++) {
if(i==cid) continue;
// sending request to sender ServerThread
STmsgTo[i].println("give list");
System.out.println("Request to "+i);
// receive file count from sender ServerThread
int cnt = Integer.parseInt(STmsgFrom[i].readLine());
System.out.println(i+" has files: "+cnt);
// sending source identity to receiver UserThread
UTmsgTo[cid].println(Integer.toString(i));
// send file count back to receiver UserThread
UTmsgTo[cid].println(Integer.toString(cnt));
// get and send file names to receiver
for(int j=0; j<cnt; j++) {
msg = STmsgFrom[i].readLine();
UTmsgTo[cid].println(msg);
}
}
} else if(msg.equals("get file")) {
// get source id and filename
int source = Integer.parseInt(UTmsgFrom[cid].readLine());
String fileName = UTmsgFrom[cid].readLine();
//System.out.println("get source id and filename");
// ask source about file
STmsgTo[source].println("give file");
STmsgTo[source].println(fileName);
boolean fileOk = Boolean.parseBoolean(STmsgFrom[source].readLine());
//System.out.println("ask source about file");
// telling receiver about file status
UTmsgTo[cid].println(Boolean.toString(fileOk));
//System.out.println("telling receiver about file");
if(fileOk) {
// get copy request from receiver
msg = UTmsgFrom[cid].readLine();
//System.out.println("receiver copy command");
if(msg.equals("yes copy")) {
System.out.println("Copying \'"+fileName+"\' from "+source+" to "+cid);
// tell sender to copy
STmsgTo[source].println("yes copy");
//System.out.println("tell sender copy command");
// copy from SENDER
// get file size
int FILE_SIZE = Integer.parseInt(STmsgFrom[source].readLine());
byte[] fileBytes = new byte[FILE_SIZE];
System.out.println("Get file size "+FILE_SIZE);
// get file data
int portion = STfileFrom[source].read(fileBytes,0,fileBytes.length);
int position = portion;
do {
portion = STfileFrom[source].read(fileBytes,position,fileBytes.length-position);
if(portion>=0) {
position += portion;
}
System.out.println("position = "+position);
} while(position<FILE_SIZE);
System.out.println("Get file data "+position);
// copy to RECEIVER
// send file size
UTmsgTo[cid].println(Integer.toString(FILE_SIZE));
//System.out.println("send file size");
// send file data
UTfileTo[cid].write(fileBytes,0,position);
UTfileTo[cid].flush();
//System.out.println("send file data");
System.out.println("Copying \'"+fileName+"\' complete");
} else {
// tell sender to ignore copy process
STmsgTo[source].println("no copy");
}
}
}
} catch(Exception ex) {
ex.printStackTrace();
}
}
}
}
Client:
package client;
import java.io.*;
import java.net.*;
public class Client {
public static void main(String[] args) throws Exception {
String msg;
InetAddress inetAddress = InetAddress.getLocalHost();
String[] allPaths= {"H:\\Study\\Lab\\Network\\Assingment 2 and lab of 5 july\\Assignment\\files\\client_1_folder",
"H:\\Study\\Lab\\Network\\Assingment 2 and lab of 5 july\\Assignment\\files\\client_2_folder",
"H:\\Study\\Lab\\Network\\Assingment 2 and lab of 5 july\\Assignment\\files\\client_3_folder"};
// connecting to welcome socket
Socket server = new Socket(inetAddress,6000);
BufferedReader receive = new BufferedReader(new InputStreamReader(server.getInputStream()));
BufferedReader receiveUser = new BufferedReader(new InputStreamReader(System.in));
PrintWriter send = new PrintWriter(server.getOutputStream(),true);
// receiving serial number
int cid = Integer.parseInt(receive.readLine());
// receiving port numbers for thread sockets
int STport = Integer.parseInt(receive.readLine());
int UTport = Integer.parseInt(receive.readLine());
// connecting sockets
Socket STsocket = new Socket(inetAddress,STport);
Socket UTsocket = new Socket(inetAddress,UTport);
System.out.println("Connected to the server.\nSerial: "+cid+"\nFolder path: "+allPaths[cid]);
ServerThread st = new ServerThread(allPaths[cid],STsocket);
UserThread ut = new UserThread(cid,allPaths[cid],UTsocket);
st.start();
ut.start();
}
}
class UserThread extends Thread {
int cid;
String msg,folderPath;
BufferedReader msgFromServer,fromUser;
PrintWriter msgToServer;
// for file
DataInputStream fileFromServer;
BufferedOutputStream writeFile;
public UserThread(int cid,String folderPath,Socket socket) {
try {
this.cid = cid;
this.folderPath = folderPath;
fromUser = new BufferedReader(new InputStreamReader(System.in));
msgFromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
msgToServer = new PrintWriter(socket.getOutputStream(),true);
// for file
fileFromServer = new DataInputStream(socket.getInputStream());
} catch(Exception ex) {
ex.printStackTrace();
}
}
#Override
public void run() {
//System.out.println("User Thread Started!");
while(true) {
try {
msg = fromUser.readLine();
if(msg.equals("get list")) {
// sending request to server
msgToServer.println("get list");
// getting file list from server
System.out.println("-------------------------------------------");
for(int i=0; i<2; i++) {
// getting source id
int source = Integer.parseInt(msgFromServer.readLine());
System.out.println("Source: "+source);
int cnt = Integer.parseInt(msgFromServer.readLine());
System.out.println("Files: "+cnt);
System.out.println("--------------");
for(int j=0; j<cnt; j++) {
msg = msgFromServer.readLine();
System.out.println(msg);
}
System.out.println("-------------------------------------------");
}
} else if(msg.equals("get file")) {
// GETTING A FILE
int source;
while(true) {
System.out.println("File Source: ");
try {
source = Integer.parseInt(fromUser.readLine());
if(0<=source && source<=2 && source!=cid) {
break;
} else {
System.out.println("Error: File source invalid. Try again.");
}
} catch(Exception ex) {
System.out.println("Error: File source invalid. Try again.");
}
}
System.out.println("File Name: ");
String fileName = fromUser.readLine();
// send request to server to check file
msgToServer.println("get file");
msgToServer.println(Integer.toString(source));
msgToServer.println(fileName);
// receiving file status
boolean fileOk = Boolean.parseBoolean(msgFromServer.readLine());
if(!fileOk) {
System.out.println("Error: File does not exist at source.");
} else {
System.out.println("File is available!!");
System.out.println("Want to copy \'"+fileName+"\'? (y/n)");
msg = fromUser.readLine();
if(msg.equals("y")||msg.equals("Y")) {
// tell server to copy file
msgToServer.println("yes copy");
// COPY PROCESS
// get file size
int FILE_SIZE = Integer.parseInt(msgFromServer.readLine());
System.out.println("File size: "+FILE_SIZE+" bytes.");
byte[] fileBytes = new byte[FILE_SIZE];
// get file data
int portion = fileFromServer.read(fileBytes,0,fileBytes.length);
int position = portion;
do {
portion = fileFromServer.read(fileBytes,position,fileBytes.length-position);
if(portion>=0) {
position += portion;
}
System.out.println("position = "+position);
} while(position<FILE_SIZE);
System.out.println("Total "+position+" bytes received.");
// write file data
File file = new File(folderPath + "\\" + fileName);
writeFile = new BufferedOutputStream(new FileOutputStream(file));
writeFile.write(fileBytes,0,position);
writeFile.flush();
writeFile.close();
System.out.println("Copying complete.");
} else {
msgToServer.println("no copy");
}
}
}
} catch(Exception ex) {
ex.printStackTrace();
}
}
}
}
class ServerThread extends Thread {
String msg,folderPath;
BufferedReader msgFromServer;
PrintWriter msgToServer;
// for file
DataOutputStream fileToServer;
BufferedInputStream readFile;
public ServerThread(String folderPath,Socket socket) {
try {
this.folderPath = folderPath;
msgFromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
msgToServer = new PrintWriter(socket.getOutputStream(),true);
// for file
fileToServer = new DataOutputStream(socket.getOutputStream());
} catch(Exception ex) {
ex.printStackTrace();
}
}
#Override
public void run() {
//System.out.println("Server Thread Started!");
while(true) {
try {
msg = msgFromServer.readLine();
if(msg.equals("give list")) {
//System.out.println("Request from server: "+msg);
File folder = new File(folderPath);
File[] fileList = folder.listFiles();
int cnt = fileList.length;
//System.out.println("Files: "+cnt);
// give file count back to server
msgToServer.println(Integer.toString(cnt));
// give file list back to server
for(int i=0; i<cnt; i++) {
msgToServer.println(fileList[i].getName());
}
} else if(msg.equals("give file")) {
// receive file name
String fileName = msgFromServer.readLine();
// telling server about file status
File file = new File(folderPath + "\\" + fileName);
boolean fileOk = file.exists();
msgToServer.println(Boolean.toString(fileOk));
if(fileOk) {
// getting copy request
msg = msgFromServer.readLine();
if(msg.equals("yes copy")) {
// COPY PROCESS
// send file size
int FILE_SIZE = (int)file.length();
msgToServer.println(Integer.toString(FILE_SIZE));
// read file data
readFile = new BufferedInputStream(new FileInputStream(file));
byte[] fileBytes = new byte[FILE_SIZE];
readFile.read(fileBytes,0,fileBytes.length);
readFile.close();
// send file data
fileToServer.write(fileBytes,0,fileBytes.length);
fileToServer.flush();
} // otherwise end of conversation
}
}
} catch(Exception ex) {
ex.printStackTrace();
}
}
}
}
I am aware that I have done some unnecessary things like giving different ports to all the different sockets. Ignore them if they are not the reason of my problem.
ServerSocket.accept() is blocking, you can't call it twice from the same thread.
Every ServerSocket must run in its own thread.

how to close a buffered reader when in mid communication

I need a bufferread to work with a client which closes when the word "CLOSE". THE client closes, I just can't get the sever to close once messages have been sent through it.
Heres what code I have:
`
import java.io.*;
import java.net.*;
class TCPClient2 {
public static void main(String argv[]) throws Exception {
String sentence;
String modifiedSentence;
BufferedReader inFromUser
= new BufferedReader(new InputStreamReader(System.in));
Socket clientSocket = new Socket("143.53.30.136", 49250);//port number and ip address of client
DataOutputStream outToServer
= new DataOutputStream(clientSocket.getOutputStream());
InputStream sin = clientSocket.getInputStream();
// Just converting them to different streams, so that string handling becomes easier.
DataInputStream inFromServer = new DataInputStream(sin);
try {
do {
System.out.print("Enter message : ");
sentence = inFromUser.readLine();
outToServer.writeBytes(sentence + '\n');
//Question B4
//if statement for closing the socket connection
if (sentence.equals("CLOSE")) {
clientSocket.close();
//closes client socket
System.out.println("Socket Closed");
//prints socket closed to tell user socket has closed
System.exit(0);
}
outToServer.writeBytes(sentence + '\n');
System.out.print("Message sent! please wait for server message: ");
modifiedSentence = inFromServer.readUTF();
System.out.println("FROM SERVER: " + modifiedSentence);
} while (!sentence.equals("CLOSE"));
} catch (IOException e) {
}
clientSocket.close();
}
}`
AND the server:
`
/*
chris and paul
*/
import java.io.*;
import java.net.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class TCPMultiThreadServer {
private static ServerSocket welcomeSocket;
//port number the server is using
private static final int PORT = 49250;
private static int clientNo =1;
public static void main(String argv[]) throws Exception
{
System.out.println("Opening port...\n");
try
{
// ServerSocket listens for new connections on specified port
welcomeSocket = new ServerSocket(PORT);
do
{
Socket client = welcomeSocket.accept();
System.out.println("\nNew client accepted.\n");
//Create a thread to handle communication with
//this client and pass the constructor for this
//thread a reference to the relevant socket...
TCPMultiThreadServer.ClientHandler handler =
new TCPMultiThreadServer().new ClientHandler(client,clientNo);
handler.start(); // Calls run() method in ClientHandler
clientNo++;
} while (true);
} catch (IOException e) {}
}
// Original work not credited
class ClientHandler extends Thread
{
private Socket client;
private BufferedReader inFromClient;
private BufferedReader text_to_Client;
private DataOutputStream outToClient;
private FileWriter Filestream;
private BufferedWriter out;
public int clientNo;
public boolean stopping;
//part A question 4, adding buffer string array to the program
private String[] buffer; //creation of buffer string array.
private int bufferI; // Index of the last thing inserted into the array
public ClientHandler(Socket socket, int clientNos)
{
//Set up reference to associated socket
client = socket;
clientNo= clientNos;
try
{
// Gets access to input/output stream of socket
inFromClient =
new BufferedReader(new InputStreamReader
(client.getInputStream()));
text_to_Client =
new BufferedReader(new InputStreamReader(System.in));
outToClient =
new DataOutputStream(client.getOutputStream());
} catch(IOException e) {}
}
public void run()
{
try
{
stopping = false;
//Question A4 buffer continued
buffer = new String[4];
//generates buffer string array containing 4 strings
bufferI = 0;
// make sure bufferIndex = 0
String clientSentence;
Thread mythread = Thread.currentThread();
do
{
//Accept message from client on socket's input stream
OutputStream sout = client.getOutputStream();
// Just converting them to different streams, so that string
// handling becomes easier.
DataOutputStream text_to_send = new DataOutputStream(sout);
clientSentence = inFromClient.readLine();
System.out.println("Message received from client number " +
clientNo + ": "+ clientSentence);
// String to be scanned to find the pattern.
String line = clientSentence;
String pattern = "[C][L][O][S][E]";
// Create a Pattern object
Pattern r = Pattern.compile(pattern);
// Now create matcher object.
Matcher m = r.matcher(line);
//if (m.find( )) {
// System.out.println("Found value: " + m.find() );
// System.out.println("Found value: " + m.group(1) );
//System.out.println("Found value: " + m.group(2) );
//} else {
// System.out.println("NO MATCH");
//}
//part B question 4 close command
//if statement for closing the socket connection if it is equal to close
if(m.matches())
{ //prints socket closed to tell user socket has closed
System.out.println("Socket connection to client number "
+ clientNo + " closed");
try
{
} catch(Exception e) {}
out.flush();
out.close(); // Close the file handler
client.close(); // Close the connection with the client,
clientNo--; // Decrement the number of clients
}
else
{
//part A question 4, adding buffer string array to the program
// looks to see if the buffer string array is full
//and also looks to see if bufferIndex is in range
if (bufferI > buffer.length-1)
{
// Print BUFFER FULL
System.out.println("BUFFER FULL");
// Clear clientSentence string
clientSentence = " ";
// For loop which travels through the buffer array of string
for (int i=0; i<buffer.length; i++)
{
// Append buffer element to clientSentence string
clientSentence += buffer[i] + " , ";
buffer[i] = null; // makes the buffer null
}
bufferI = 0; // Reset bufferI back to 0 so writing to the buffer can restarted
// prints buffer cleared back to the clients
text_to_send.writeUTF("BUFFER CLEARED :" +
clientSentence);
}
else
{
buffer[bufferI] = clientSentence;
System.out.println("Buffer " + bufferI+ ": " +
buffer[bufferI]);
bufferI++;
System.out.println("Enter Message: ");
// Reads message from server interface
// and sends it to the client
clientSentence = text_to_Client.readLine();
text_to_send.writeUTF(clientSentence);
System.out.println("Your message: " +
clientSentence);
}
}
if (mythread.activeCount() == 2 &&
(clientNo ==0 || clientNo >0) &&
clientSentence.equals("CLOSE"))
{
System.exit(0);
}
} while(!clientSentence.equals("CLOSE"));
client.close();
} catch(IOException e) {}
}
}
}
`

Socket program to send and receive user defined objects not working

I have a user defined class Message, whose object I would like to pass between the client and the server.
The Message class is as follows:
import java.io.Serializable;
public class Message implements Serializable
{
String CorS;
int data_id;
int status_id;
Integer value;
boolean withdraw;
public Message()
{
CorS = null;
data_id = 0;
status_id = 0;
value = 0;
withdraw = false;
}
public Message(String CorS, int data_id, int status_id, Integer value)
{
this.CorS = CorS;
this.data_id = data_id;
this.status_id = status_id;
this.value = value;
}
public Message(boolean withdraw)
{
this.withdraw = withdraw;
}
}
The code in the client side which sends the object to the server is as follows:
Socket s = null;
ObjectInputStream in = null;
ObjectOutputStream out = null;
String hostname = null;
int port_no = 0;
HashMap<String, Integer> map = null;
Message m = null;
map = servers.get("Server" + server);
for(String key : map.keySet())
{
hostname = key;
port_no = map.get(key);
}
//System.out.println(hostname + " " + port_no);
s = new Socket(hostname, port_no);
in = new ObjectInputStream(new BufferedInputStream(s.getInputStream()));
out = new ObjectOutputStream(new BufferedOutputStream(s.getOutputStream()));
s_now = s;
m = new Message(client, data, 0, 0);
out.writeObject(m);
out.flush();
System.out.println("Sent obj");
Similarly, the code on the Server side is as follows:
while (true)
{
try
{
System.out.println("Waiting for client on port " + serverSocket.getLocalPort() + "...");
Socket server = serverSocket.accept();
System.out.println("Just connected to " + server.getRemoteSocketAddress());
ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(server.getInputStream()));
//ObjectOutputStream out = new ObjectOutputStream(server.getOutputStream());
Message m = (Message) in.readObject();
System.out.println(m.value);
}
catch (IOException e)
{
e.printStackTrace();
break;
}
catch (ClassNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
The problem is that the object is not getting printed. The output I get is as follows:
Waiting for client on port 1051...
Just connected to /127.0.0.1:59216
Any help in this regard will be greatly appreciated. Thanks :)
You need to create the ObjectOutputStream before the ObjectInputStream at both ends.
The reason is that, as described in the Javadoc, the respective constructors write and read a stream header. So the input stream constructor can't return until the output stream constructor at the peer has executed. So if you construct both input streams first there is a deadlock.

One thread stopping too early regardless of CyclicBarrier

I am aware of the fact that the following code may seem vulgar, but I am new to these things and just tried everything in order to get it to work..
Problem: Even though I am using (possible in a wrong way) a CyclicBarrier, one - and seems to always be the same - thread stops too soon and prints out his vector, leaving 1 out of 11 of those "Incoming connection" messages absent. There is probably something terribly wrong with the last iteration of my loop, but I can't seem to find what exactly.. Now the program just loops waiting to process the last connection.
public class VectorClockClient implements Runnable {
/*
* Attributes
*/
/*
* The client number is store to provide fast
* array access when, for example, a thread's own
* clock simply needs to be incremented.
*/
private int clientNumber;
private File configFile, inputFile;
int[] vectorClock;
/*
* Constructor
* #param
* - File config
* - int line
* - File input
* - int clients
*/
public VectorClockClient(File config, int line, File input, int clients) {
/*
* Make sure that File handles aren't null and that
* the line number is valid.
*/
if (config != null && line >= 0 && input != null) {
configFile = config;
inputFile = input;
clientNumber = line;
/*
* Set the array size to the number of lines found in the
* config file and initialize with zero values.
*/
vectorClock = new int[clients];
for (int i = 0; i < vectorClock.length; i++) {
vectorClock[i] = 0;
}
}
}
private int parsePort() {
int returnable = 0;
try {
FileInputStream fstream = new FileInputStream(configFile.getName());
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine = "";
for (int i = 0; i < clientNumber + 1; i++) {
strLine = br.readLine();
}
String[] tokens = strLine.split(" ");
returnable = Integer.parseInt(tokens[1]);
}
catch (Exception e) {
e.printStackTrace();
}
System.out.println("[" + clientNumber + "] returned with " + returnable + ".");
return returnable;
}
private int parsePort(int client) {
int returnable = 0;
try {
FileInputStream fstream = new FileInputStream(configFile.getName());
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine = "";
for (int i = 0; i < client; i++) {
strLine = br.readLine();
}
String[] tokens = strLine.split(" ");
returnable = Integer.parseInt(tokens[1]);
}
catch (Exception e) {
e.printStackTrace();
}
return returnable;
}
private int parseAction(String s) {
int returnable = -1;
try {
FileInputStream fstream = new FileInputStream(configFile.getName());
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String[] tokens = s.split(" ");
if (!(Integer.parseInt(tokens[0]) == this.clientNumber + 1)) {
return -1;
}
else {
if (tokens[1].equals("L")) {
vectorClock[clientNumber] += Integer.parseInt(tokens[2]);
}
else {
returnable = Integer.parseInt(tokens[2]);
}
}
}
catch (Exception e) {
e.printStackTrace();
}
return returnable;
}
/*
* Do the actual work.
*/
public void run() {
try {
InitClients.barrier.await();
}
catch (Exception e) {
System.out.println(e);
}
int port = parsePort();
String hostname = "localhost";
String strLine;
ServerSocketChannel ssc;
SocketChannel sc;
FileInputStream fstream;
DataInputStream in;
BufferedReader br;
boolean eof = false;
try {
ssc = ServerSocketChannel.open();
ssc.socket().bind(new InetSocketAddress(hostname, port));
ssc.configureBlocking(false);
fstream = new FileInputStream("input_vector.txt");
in = new DataInputStream(fstream);
br = new BufferedReader(new InputStreamReader(in));
try {
InitClients.barrier.await();
}
catch (Exception e) {
System.out.println(e);
}
while (true && (eof == false)) {
sc = ssc.accept();
if (sc == null) {
if ((strLine = br.readLine()) != null) {
int result = parseAction(strLine);
if (result >= 0) {
//System.out.println("[" + (clientNumber + 1)
//+ "] Send a message to " + result + ".");
try {
SocketChannel client = SocketChannel.open();
client.configureBlocking(true);
client.connect(
new InetSocketAddress("localhost",
parsePort(result)));
//ByteBuffer buf = ByteBuffer.allocateDirect(32);
//buf.put((byte)0xFF);
//buf.flip();
//vectorClock[clientNumber] += 1;
//int numBytesWritten = client.write(buf);
String obj = Integer.toString(clientNumber+1);
ObjectOutputStream oos = new
ObjectOutputStream(
client.socket().getOutputStream());
oos.writeObject(obj);
oos.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
else {
eof = true;
}
}
else {
ObjectInputStream ois = new
ObjectInputStream(sc.socket().getInputStream());
String clientNumberString = (String)ois.readObject();
System.out.println("At {Client[" + (clientNumber + 1)
+ "]}Incoming connection from: "
+ sc.socket().getRemoteSocketAddress()
+ " from {Client[" + clientNumberString + "]}");
sc.close();
}
try {
InitClients.barrier.await();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
catch (Exception e) {
e.printStackTrace();
}
printVector();
}
private void printVector() {
System.out.print("{Client[" + (clientNumber + 1) + "]}{");
for (int i = 0; i < vectorClock.length; i++) {
System.out.print(vectorClock[i] + "\t");
}
System.out.println("}");
}
}
To clarify, here are the formats of the files used. Config contains hostnames and ports used by clients that are threads and input file's rows mean either "this client sends a message to that client" or "this client increments his logical clock by some constant value".
1 M 2 (M means sending a message)
2 M 3
3 M 4
2 L 7 (L means incrementing clock)
2 M 1
...
127.0.0.1 9000
127.0.0.1 9001
127.0.0.1 9002
127.0.0.1 9003
...
I would look at the logic related to when you are expecting an incoming socket connection. From your question it looks like you expect a certain number of incoming socket connections (potentially an incoming connection after every outgoing message?). Since you are using non-blocking I/O on the incoming socket it is always possible that your while statement loops before an incoming socket could be established. As a result, a thread would be able to continue and read the next line from the file without receiving a connection. Since your end state is reached once the end of the file is reached, it is possible that you may miss an incoming socket connection.
I would add some simple print outs that displays when you read from the file, when you send a message and when you receive an incoming connection. That should quickly tell you whether or not a particular thread is missing an expected incoming connection. If it turns out that the problem is due to the non-blocking I/O, then you may need to disable non-blocking I/O when you expect an incoming socket or implement a control that keeps track of how many incoming sockets you expect and continues until that goal is met.
Hope this helps.

Categories