Socket client blocks forever - java

I'm coding socket client in Java.
In the program, I want to get information from server.
When the server receives "GET_LIGHTS" command, it sends back data in JSON format.
But in my code, bw.write() and bw.flush() doesn't work before socket.close().
So, the BufferedReader object is not ready: br.ready() returns false.
Is there any mistake in my code?
The client code is shown bellow.
package monitor;
import java.io.*;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.ArrayList;
public class SocketClient {
static private int port;
static private String hostName;
private Socket socket;
public SocketClient(String host, int port) {
this.hostName = host;
this.port = port;
}
// get lights by JSON
public void getLights() {
try {
// generate socket
InetSocketAddress endpoint = new InetSocketAddress(hostName, port);
socket = new Socket();
socket.connect(endpoint);
// setting
OutputStreamWriter out = new OutputStreamWriter(socket.getOutputStream());
BufferedWriter bw = new BufferedWriter(out);
InputStreamReader in = new InputStreamReader(socket.getInputStream());
BufferedReader br = new BufferedReader(in);
// send command
bw.write("GET_LIGHTS");
bw.flush();
// receive message from server
System.out.println(br.readLine());
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void initLights(ArrayList<Light> lights) {
getLights();
}
}
Edited:
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class SocketServer extends Thread{
static final int PORT = 44344;
static private ILS ils;
private ServerSocket serverSocket;
private Socket socket;
public SocketServer(ILS ils) {
this.ils = ils;
}
#Override
public void run() {
serverSocket = null;
System.out.println("Server: listening");
try {
serverSocket = new ServerSocket(PORT);
while(true){
socket = serverSocket.accept();
BufferedReader br = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
ArrayList<String> cmd = new ArrayList<>();
String in;
while( (in = br.readLine()) != null ){
cmd.add(in);
}
command(cmd);
if( socket != null){
socket.close();
}
}
} catch (IOException e) {
e.printStackTrace();
}
if( serverSocket != null){
try {
serverSocket.close();
serverSocket = null;
} catch (IOException e) {
e.printStackTrace();
}
}
}
// send message to client
private void sendMessage(String str) {
System.out.println(str);
try {
OutputStream output = socket.getOutputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(output));
bw.write(str + "¥n");
bw.flush();
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// error
private void printError(String err) {
String str = "ERROR; ";
str += err;
sendMessage(str);
}
public void command(ArrayList<String> cmd) {
String mode = cmd.get(0);
if(mode == null){
}else switch(mode){
case "MANUAL_SIG-ALL":
System.out.println("全照明一括 信号値指定調光");
manualSigAll(cmd.get(1));
break;
case "MANUAL_SIG-INDIVIDUAL":
System.out.println("全照明独立 信号値指定調光");
manualSigIndividual(cmd.get(1));
break;
case "MANUAL_ID-SIG":
System.out.println("照明ID・信号値指定調光");
manualIDSig(cmd.get(1));
break;
case "MANUAL_ID-RELATIVE":
System.out.println("照明ID・相対信号値指定調光");
break;
case "DOWNLIGHT_ALL":
System.out.println("Downlight: All Control");
downlightAll(cmd.get(1));
break;
case "DOWNLIGHT_INDIVIDUAL":
System.out.println("Downlight: Individual control");
downlightIndividual(cmd.get(1));
break;
case "GET_LIGHTS":
System.out.println("Sending lights via JSON");
sendLights();
break;
default:
System.out.println("Error: 不明なmode command");
}
}
// 全照明一括 信号値指定調光
private void manualSigAll(String sigs) {
if(sigs == null) {
System.out.println("信号値のフォーマットを確認してください");
} else {
ArrayList<Integer> s = new ArrayList<>();
String[] buf = sigs.split(",");
for(String i:buf) s.add(Integer.parseInt(i));
for(Light l: ils.getLights()) {
l.setLumPct((double)s.get(0)/255.0*100.0);
l.setSignal(s.get(0), s.get(1));
}
}
// 調光
ils.downlightDimmer.send();
}
// 全照明独立 信号値指定調光
private void manualSigIndividual(String sigs) {
if(sigs == null) {
System.out.println("信号値のフォーマットを確認してください");
} else {
ArrayList<Integer> s = new ArrayList<>();
String[] buf = sigs.split(",");
for(String i:buf) s.add(Integer.parseInt(i));
for(int i=0; i<ils.getLights().size(); i++) {
ils.getLights().get(i).setSignal(s.get(0), s.get(1));
s.remove(0);
s.remove(0);
}
}
ils.downlightDimmer.send();
}
// 照明ID・信号値指定調光
private void manualIDSig(String sigs) {
if(sigs == null) {
System.out.println("信号値のフォーマットを確認してください");
} else {
ArrayList<Integer> s = new ArrayList<>();
String[] buf = sigs.split(",");
for(String i:buf) s.add(Integer.parseInt(i));
System.out.println(s.get(0));
ils.getLight(s.get(0)).setSignal(s.get(1), s.get(2));
}
ils.downlightDimmer.send();
}
private void downlightAll(String cmd) {
if(cmd == null) {
printError("Check for data command.");
} else {
ArrayList<Double> data = new ArrayList<>();
String[] buf = cmd.split(",");
for(String i:buf) data.add(Double.parseDouble(i));
for(Light l: ils.getLights()) {
l.setLumPct(data.get(0));
l.setTemperature(data.get(1));
}
}
// dimming
ils.downlightDimmer.send();
}
private void downlightIndividual(String cmd) {
if(cmd == null) {
printError("Check for data command.");
} else {
ArrayList<Integer> id = new ArrayList<>();
ArrayList<Double> lumPct = new ArrayList<>();
ArrayList<Integer> temp = new ArrayList<>();
String[] buf = cmd.split(",");
if(buf.length % 3 != 0) {printError("invalid number of data.");}
for(int i=0; i<buf.length/3; i++) {
int n = i*3;
try {
id.add(Integer.parseInt(buf[n]));
lumPct.add(Double.parseDouble(buf[n + 1]));
temp.add(Integer.parseInt(buf[n + 2]));
} catch (Exception e) {
printError(e.getMessage());
return;
}
}
while (id.size() > 0) {
// update light object
Light light = ils.getLight(id.get(0));
light.setLumPct(lumPct.get(0));
light.setTemperature(temp.get(0));
// remove data from array list
id.remove(0);
lumPct.remove(0);
temp.remove(0);
}
// dimming
ils.downlightDimmer.send();
}
}
private void sendLights() {
ObjectMapper mapper = new ObjectMapper();
String json = "";
try {
json = mapper.writeValueAsString(ils.getLights());
} catch (JsonProcessingException e) {
e.printStackTrace();
}
// output
sendMessage(json);
}
}

If your server is using readLine(), as is probable, it will block until you close the connection, because you aren't sending a line.
Add bw.newLine() before the flush().
EDIT As predicted, your server isn't sending lines, so it needs the same treatment as above. However there is an anterior problem:
while( (in = br.readLine()) != null ){
cmd.add(in);
}
This loop in the server cannot possibly exit until the client closes the connection. You should process a line at a time in the server, or else moderate your expectations of the client's behaviour.

Related

Java application with TCP sockets is using 100% of CPU

The server has to continuously listen for incoming connections and perform some logic on the data received. Every time I run the application, the CPU usage is more than 90%. Earlier I thought that the while loop might be spinning (busy waiting), but the readLine() is supposed to be a blocking call, so I don't think that is the case. Any help is appreciated!
The following is the server code:
public void listen() throws IOException
{
try( ServerSocket serverSocket = new ServerSocket(port);
Socket clientSocket = serverSocket.accept();
DataOutputStream outputStream = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));)
{
String data = null;
while((data = bufferedReader.readLine()) != null)
{
Message message = Message.deserializeMessage(data);
synchronized (PeerNode.requestHistory)
{
if(PeerNode.requestHistory.keySet().contains(message))
{
continue;
}
}
if(message.getType() == 0 && message.getHopCount() < 1) {
continue;
}
switch(message.getType()) {
case 0:
synchronized (PeerNode.sharedRequestBuffer){
PeerNode.sharedRequestBuffer.offer(message);
}
break;
case 1:
synchronized (PeerNode.sharedReplyBuffer) {
PeerNode.sharedReplyBuffer.offer(message);
}
break;
case 2:
synchronized (PeerNode.numberOfItems) {
if(PeerNode.numberOfItems > 0) {
PeerNode.numberOfItems -= 1;
}
outputStream.writeBytes("0" + "\n");
}
break;
}
synchronized (PeerNode.requestHistory) {
PeerNode.requestHistory.put(message, 0);
}
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
Edit: Added deserialize() method
public static Message deserializeMessage(String s)
{
Message m = new Message();
String[] objArray = s.split("#");
String[] list = objArray[2].split(",");
m.setProductName(objArray[0]);
m.setProductId(Integer.parseInt(objArray[1]));
List<Integer> tempList = new ArrayList();
for(int i=0; i<list.length; i++)
{
if(list[i].length() == 0)
continue;
tempList.add(Integer.parseInt(list[i]));
}
m.setMessagePath(tempList);
m.setHopCount(Integer.parseInt(objArray[3]));
m.setType(Integer.parseInt(objArray[4]));
m.setRequestId(Integer.parseInt(objArray[5]));
m.setSourcePeerId(Integer.parseInt(objArray[6]));
m.setDestinationSellerId(Integer.parseInt(objArray[7]));
m.setDestinationSellerLocation(Integer.parseInt(objArray[8]));
return m;
}
Edit 2: Changed deserialize() to use Scanner():
public static Message deserializeMessage(String s)
{
Message m = new Message();
Scanner sc = new Scanner(s);
sc.useDelimiter("#");
m.setProductName(sc.next());
m.setProductId(Integer.parseInt(sc.next()));
List<Integer> tempList = new ArrayList();
Scanner sct = new Scanner(sc.next());
sct.useDelimiter(",");
while(sct.hasNext())
{
tempList.add(Integer.parseInt(sct.next()));
}
m.setMessagePath(tempList);
m.setHopCount(Integer.parseInt(sc.next()));
m.setType(Integer.parseInt(sc.next()));
m.setRequestId(Integer.parseInt(sc.next()));
m.setSourcePeerId(Integer.parseInt(sc.next()));
m.setDestinationSellerId(Integer.parseInt(sc.next()));
m.setDestinationSellerLocation(Integer.parseInt(sc.next()));
return m;
}
Edit: Updated Server Code:
private ExecutorService executor = Executors.newFixedThreadPool(15);
public void listen() throws IOException
{
serverSocket = new ServerSocket(port);
while (!Thread.interrupted()) {
try
{
//Server, Listening........
clientSocket = serverSocket.accept();
ServerExecutor serverExecutor = new ServerExecutor(peerID, clientSocket);
executor.submit(serverExecutor);
}
catch (IOException e)
{
e.printStackTrace();
}
}
serverSocket.close();
}
ServerExecutor class:
public ServerExecutor(int _peerID, Socket _clientSocket)
{
this.peerID = _peerID;
this.clientSocket = _clientSocket;
}
public void run()
{
try( DataOutputStream outputStream = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));)
{
String data = null;
while((data = bufferedReader.readLine()) != null)
{
Message message = Message.deserializeMessage(data);
synchronized (PeerNode.requestHistory)
{
if(PeerNode.requestHistory.keySet().contains(message))
{
continue;
}
}
if(message.getType() == 0 && message.getHopCount() < 1) {
continue;
}
switch(message.getType()) {
case 0:
synchronized (PeerNode.sharedRequestBuffer){
PeerNode.sharedRequestBuffer.offer(message);
}
break;
case 1:
synchronized (PeerNode.sharedReplyBuffer) {
PeerNode.sharedReplyBuffer.offer(message);
}
break;
case 2:
synchronized (PeerNode.numberOfItems) {
if(PeerNode.numberOfItems > 0) {
PeerNode.numberOfItems -= 1;
}
outputStream.writeBytes("0" + "\n");
}
break;
}
synchronized (PeerNode.requestHistory) {
PeerNode.requestHistory.put(message, 0);
}
}
clientSocket.close();
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
Updated deserialize():
public static Message deserializeMessage(String s)
{
Message m = new Message();
Scanner sc = new Scanner(s);
sc.useDelimiter("#");
m.setProductName(sc.next());
m.setProductId(sc.nextInt());
List<Integer> tempList = new ArrayList();
Scanner sct = new Scanner(sc.next());
sct.useDelimiter(",");
while(sct.hasNext())
{
tempList.add(sct.nextInt());
}
m.setMessagePath(tempList);
m.setHopCount(sc.nextInt());
m.setType(sc.nextInt());
m.setRequestId(sc.nextInt());
m.setSourcePeerId(sc.nextInt());
m.setDestinationSellerId(sc.nextInt());
m.setDestinationSellerLocation(sc.nextInt());
return m;
}
Are you using different thread for each new client connection and also this kinda code will never occupy such a high % of CPU load. Is there some other functionality that's running in the background as well?
Edit:
Maybe you can try something like this?
while (true)
{
Socket s = null;
ServerSocket serverSocket = new ServerSocket(5555);
try
{
s = ss.accept(); //ss is the server socket object
DataOutputStream out = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader int = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
//create a new Thread for the client
Thread t = new TaskHandler(s, in, out); //run method of Task Handler can have the code you want to execute for each connected client
t.start();
}
catch (Exception e){
s.close();
e.printStackTrace();
}
}
Does this help?

How to access a string called "numberPart" from a different file (multithreaded java socket programming)

There is a string called numberPart inside a thread class called ServerRecieve. The location where .start() is being called is inside of a different class called Server.
The 'numberPart' will eventually be used as a port for file transferring later on.
My question is: How do I access the numberPart variable inside of the class called Server?
Screenshot of code running (server on left window, client on the right):
server on left window, client on the right
In the left window of the screenshot (server) you can see the that the first port number of the right window's command line argument which is 4021 being sent via a text message, and the server successfully receives it with the message "File transfer port found: 4021". Unfortunately this variable is located inside a different class. I would like to know how to access that variable inside the class called Server.
ServerRecieve code:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
public class ServerRecieve extends Thread
{
Socket servSocket;
boolean m_bRunThread = true;
boolean ServerOn = true;
public ServerRecieve(Socket s)
{
super();
servSocket = s;
}
public void run()
{
while(true)
{
try
{
BufferedReader readFromClient = new BufferedReader(new InputStreamReader(servSocket.getInputStream()));
String fromClient = readFromClient.readLine();
String a = fromClient;
int i;
for(i = 0; i < a.length(); i++)
{
char c = a.charAt(i);
if( '0' <= c && c <= '9' )
{
break;
}
}
String alphaPart = a.substring(0, i);
String numberPart = a.substring(i);
System.out.println("Recieved from client: " + alphaPart +"\n");
System.out.println("File transfer port found: " + numberPart + "\n");
//String[] filePortNumber = null;
//filePortNumber[0] = numberPart;
// Server thing = new Server(filePortNumber);
if(fromClient.equals(null))
{
System.exit(0);
}
OutputOptions();
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
}
}
}
void OutputOptions()
{
System.out.println("Enter an option ('m', 'f', 'x'): ");
System.out.println("(M)essage (send)");
System.out.println("(F)ile (request) ");
System.out.println("e(X)it ");
}
}
Server source:
import java.io.*;
import java.net.*;
import java.util.*;
import javax.imageio.IIOException;
public class Server
{
private String[] serverArgs;
public Socket socket;
public Socket fileSocket;
public boolean keepRunning = true;
public int ConnectOnce = 0;
public String option = "";
public boolean isConnected = false;
public String FILE_TO_SEND = "/Users/nanettegormley/Documents/workspace/assignment2/src/servers/cdm.jpg";
public Server(String[] args) throws IOException
{
// set the instance variable
this.serverArgs = args;
if(ConnectOnce == 0)
{
int port_number1 = Integer.valueOf(serverArgs[1]);
ServerSocket serverSocket = new ServerSocket(port_number1);
socket = serverSocket.accept();
ConnectOnce = 4;
isConnected = true;
}
}
public String[] serverRun2(String[] args) throws IOException
{
serverArgs = args;
serverArgs = Arrays.copyOf(args, args.length);
serverSend.start();
return serverArgs;
}
Thread serverSend = new Thread()
{
public void run()
{
OutputOptions();
while(isConnected)
{
try
{
ServerRecieve serverThread = new ServerRecieve(socket);
serverThread.start();
// input the message from standard input
BufferedReader input2= new BufferedReader(new InputStreamReader(System.in));
option = input2.readLine();
if(option.equals("m") || option.equals("M"))
{
StandardOutput();
}
if(option.equals("f") || option.equals("F"))
{
FileTransferSend();
}
if(option.equals("x") || option.equals("X"))
{
System.exit(0);
}
}
catch ( Exception e )
{
System.out.println( e.getMessage() );
}
}
}
};
public void StandardOutput()
{
try
{
//Send the message to the server
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
//creating message to send from standard input
String newmessage = "";
try
{
System.out.println("Enter your message: ");
// input the message from standard input
BufferedReader input2= new BufferedReader(new InputStreamReader(System.in));
String line = "";
line= input2.readLine();
newmessage += line + " ";
}
catch ( Exception e )
{
System.out.println( e.getMessage() );
}
String sendMessage = newmessage;
bw.write(sendMessage + "\n");
bw.newLine();
bw.flush();
System.out.println("Message sent to client: "+sendMessage);
StandardInput();
//run();
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
}
}
void FileTransferSend()
{
//connect to the filetransfer
try
{
System.out.println("Which file do you want? ");
Scanner scanner = new Scanner(System.in);
String filename = scanner.nextLine();
FileInputStream fis = new FileInputStream(new File(filename));
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(fileSocket.getOutputStream()));
int element;
while((element = fis.read()) !=1)
{
dos.write(element);
}
byte[] byteBuffer = new byte[1024]; // buffer
while(fis.read(byteBuffer)!= -1)
{
dos.write(byteBuffer);
}
OutputOptions();
// dos.close();
// fis.close();
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
}
}
void OutputOptions()
{
System.out.println("Enter an option ('m', 'f', 'x'): ");
System.out.println("(M)essage (send)");
System.out.println("(F)ile (request) ");
System.out.println("e(X)it ");
}
public void StandardInput()
{
OutputOptions();
while(true)
{
try
{
// input the message from standard input
BufferedReader input2= new BufferedReader(new InputStreamReader(System.in));
String line2 = "";
option= input2.readLine();
if(option.equals("m") || option.equals("M"))
{
StandardOutput();
}
if(option.equals("f") || option.equals("F"))
{
FileTransferSend();
}
if(option.equals("x") || option.equals("X"))
{
System.exit(0);
}
}
catch ( Exception e )
{
System.out.println( e.getMessage() );
}
finally
{
}
}
}
}
Full code with all files:
https://www.dropbox.com/s/0yq47gapsd3dgjp/folder33.zip?dl=0
My question is: What changes can I make to the code that would allow me to access numberPart while being inside Server?
EDIT: Is there a way to bump a question that hasn't gotten any answers or should I just delete this one and repost it somewhere?
I would think that you could use either a listener or callback pattern to solve this.
(I'm losing my Java memory now that I'm doing C# so please bear with me..)
interface PortAssignable {
public assignPort(int port);
}
Then have the Server class implement that interface
public Server implements PortAssignable {
...
}
And ServerReceive
// Constructor
public ServerRecieve(Socket s, PortAssignable portNotifyListener) {
_portNotifyListener = portNotifyListener;
... your other code ...
}
Make sure when you create an instance of ServerReceive, you pass in your Server instance, via this.
ServerRecieve serverThread = new ServerRecieve(socket, this);
Now, when you get your numberPart, your next line can be
_portNotifyListener.assignPort(numberPart);
How you choose to implement the assignPort method in your Server class is up to you.
P.S. I saw this question from /r/programming.

Handle more clients

Right now my server only can handle one client at a time. I am trying to use a Thread so that the server can handle several clients, but I am doing it wrong. I have added the thread in the try/catch clause where the serverSocket accepts the client, but this makes no difference. I don't get an error or anything, but it just doesn't work.
So what I want to do, is make the server not freeze at one client, but still accept several clients.
Here is the server code:
import java.io.*;
import java.net.*;
public class Server {
private BufferedReader reader;
private PrintWriter writer;
private int port;
public Server(int port)
{
this.port = port;
}
private String getSeverAddress() {
String host = null;
try {
InetAddress adr = InetAddress.getLocalHost();
host = adr.getHostAddress();
} catch (UnknownHostException e) {
e.printStackTrace();
}
return host;
}
public void startServer() {
print("Contact this sever on address: " + getSeverAddress() + " port: " + port);
ServerSocket ss = null;
Socket socket = null;
Thread clientThread = null;
try {
ss = new ServerSocket(port);
socket = ss.accept();
clientThread = new Thread(new Client(socket));
clientThread.start();
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
writer = new PrintWriter(socket.getOutputStream(), true);
String msg = null;
while (( msg = reader.readLine()) != null) {
print("System out: " + msg);
if(msg.equals("Bye")) {
print("Client left");
break;
}
}
ss.close();
socket.close();
reader.close();
writer.close();
} catch(SocketException e) {
e.printStackTrace();
} catch (IOException i ) {
i.printStackTrace();
return;
}
}
private void print(String msg) {
System.out.println(msg);
}
public static void main(String[] args) {
Server server = new Server(1111);
server.startServer();
}
}
Here is the client code:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class Client implements Runnable{
private Socket client;
private BufferedReader reader;
private PrintWriter writer;
public Client(Socket socket)
{
client = socket;
try{
reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
writer = new PrintWriter(client.getOutputStream(), true);
} catch (Exception e) {
e.printStackTrace();
return;
}
}
#Override
public void run() {
String msg = null;
BufferedReader r = null;
try {
r = new BufferedReader(new InputStreamReader(System.in));
} catch (Exception e1) {
e1.printStackTrace();
}
System.out.println("Write message to server");
while(true) {
try {
msg = r.readLine();
if(msg.equals("Quit") || msg == null) {
print("Disconnect");
break;
}
} catch (IOException e) {
e.printStackTrace();
}
writeToServer(msg);
}
try {
r.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void writeToServer(String msg) {
writer.println(msg);
}
private void print(String msg) {
System.out.println(msg);
}
public static void main(String[] args) {
Socket socket = null;
try {
socket = new Socket("localhost", 1111);
} catch (Exception e) {
e.printStackTrace();
}
Client client = new Client(socket);
client.run();
}
}
You are still trying to handle clients in your main thread. Main thread should just accept new connections and start new threads. You also have to do accept in a loop so multiple connections can be accepted:
ss = new ServerSocket(port);
while(true) {
Socket socket = ss.accept();
Thread clientThread = new Thread(new Runnable() {
public void run() {
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
String msg = null;
while (( msg = reader.readLine()) != null) {
print("System out: " + msg);
if(msg.equals("Bye")) {
print("Client left");
break;
}
}
socket.close();
reader.close();
writer.close();
}});
clientThread.start();
}
You need to put your ss.accept() into a while loop and create a new Thread for every client accepted, which handles the connection.

BufferedReader from server does not work

In this code I can correctly receive a request using BufferedReader inClient, created on the client socket.
Then I send the request to the server and I see the server gets it.
But then, when I try to read the reply from the server (using BufferedReader inServer on the socket of the server), it always ends in IOException: Impossible read from server.
I am referring to the block ################
Do you know any possible reasons?
import java.io.*;
import java.net.Socket;
import java.net.ServerSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class ProxyMain {
public static void main(String argv[]) {
int proxyPort = 55554;
String proxyAddr = "127.0.0.1";
ServerSocket proxySocket = null;
try {
proxySocket = new ServerSocket(proxyPort, 50, InetAddress.getByName("127.0.0.1"));
}
catch (Exception e) {
System.err.println("Impossible to create socket server!");
System.out.flush();
System.exit(1);
}
System.out.printf("Proxy active on port: %d and on address %s\n", proxyPort, proxySocket.getInetAddress());
System.out.println();
while (true) {
Socket client = null;
Socket sockServ = null;
BufferedReader inClient = null;
PrintWriter outClient = null;
BufferedReader inServer = null;
PrintWriter outServer = null;
String request = new String();
String tmp = new String();
String reply = new String();
String tmpReply = new String();
try {
client = proxySocket.accept();
System.out.println("Connected to: ");
System.out.println(client.getInetAddress().toString());
System.out.printf("On port %d\n", client.getPort());
System.out.println();
inClient = new BufferedReader(new InputStreamReader(client.getInputStream()));
outClient = new PrintWriter(client.getOutputStream(), true);
}
/*catch (IOException e) {
System.err.println("Couldn't get I/O for connection accepted");
System.exit(1);
}*/
catch (Exception e) {
System.out.println("Error occurred!");
System.exit(1);
}
System.out.println("Received request:");
try{
for (int i = 0; i<2; i++) {
tmp = inClient.readLine();
request = request + tmp;
}
inClient.close();
}
catch (IOException ioe) {
System.err.println("Impossible to read mhttp request!");
System.exit(1);
}
System.out.println(request);
System.out.println();
try {
sockServ = new Socket("127.0.0.1", 55555);
outServer = new PrintWriter(sockServ.getOutputStream(), true);
inServer = new BufferedReader(new InputStreamReader(sockServ.getInputStream()));
}
catch (UnknownHostException e) {
System.err.println("Don't know about host: 127.0.0.1:55555");
System.exit(1);
}
catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to: 127.0.0.1:55555");
System.exit(1);
}
outServer.println(request);
outServer.close();
try {
#################################################
while ((tmpReply = inServer.readLine()) != null) {
System.out.println(tmpReply);
reply = reply + tmpReply;
}
inServer.close();
sockServ.close();
}
catch (IOException ioe) {
System.err.println("Impossible to read from server!");
System.exit(1);
}
outClient.println(reply);
outClient.close();
try {
client.close();
}
catch (IOException ioe) {
System.err.printf("Impossible to close connection with %s:%d\n", client.getInetAddress().toString(), client.getPort());
}
}
}
}
UPDATE:
It seems that if I do:
boolean res = inServer.ready();
it always return false.
So Server is not ready to send the reply but this is strange...with my Project in C e Python it worked immediately. Why should java be different?
When you close outServer, you close the underlying socket. if you just want to close the output and keep the input open, you need to use Socket.shutdownOutput(). note, you have the same problem when you close inClient.
This works, maybe you can get some ideas from it...
ChatServer - broadcasts to all connected clients
In one command prompt: java ChartServer
In another: java ChatClient localhost (or the ip address of where the server is running)
And another: java ChatClient localhost (or the ip address of where the server is running)
Start chatting in the client windows.
Server like this...
// xagyg wrote this, but you can copy it
import java.io.*;
import java.net.*;
import java.util.*;
public class ChatServer {
public static List list = new ArrayList();
public static void main(String[] args) throws Exception {
ServerSocket svr = new ServerSocket(4444);
System.out.println("Chat Server started!");
while (true) {
try {
Socket s = svr.accept();
synchronized(list) {
list.add(s);
}
new Handler(s, list).start();
}
catch (IOException e) {
// print out the error, but continue!
System.err.println(e);
}
}
}
}
class Handler extends Thread {
private Socket s;
private String ipaddress;
private List list;
Handler (Socket s, List list) throws Exception {
this.s = s;
ipaddress = s.getInetAddress().toString();
this.list = list;
}
public void run () {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(s.getInputStream()));
String message;
//MyDialog x = (MyDialog)map.get(ipaddress.substring(1));
while ((message = reader.readLine()) != null) {
if (message.equals("quit")) {
synchronized(list) {
list.remove(s);
}
break;
}
synchronized(list) {
for (Object object: list) {
Socket socket = (Socket)object;
if (socket==s) continue;
PrintWriter writer = new PrintWriter(socket.getOutputStream());
writer.println(ipaddress + ": " + message);
writer.flush();
}
}
}
try { reader.close(); } catch (Exception e) {}
}
catch (Exception e) {
System.err.println(e);
}
}
}
Client like this ...
// xagyg wrote this, but you can copy it
import java.util.*;
import java.io.*;
import java.net.*;
public class ChatClient {
public static void main(String[] args) throws Exception {
Socket s = new Socket(args[0], 4444);
BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
PrintWriter out = new PrintWriter(s.getOutputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String message;
new SocketReader(in).start();
while ((message = reader.readLine())!=null) {
out.println(message);
out.flush();
if (message.equals("quit")) break;
}
in.close();
out.close();
}
}
class SocketReader extends Thread {
BufferedReader in;
public SocketReader(BufferedReader in) {
this.in = in;
}
public void run() {
String message;
try {
while ((message = in.readLine())!=null) {
System.out.println(message);
}
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
}

Overriding the run() method to accept a parameter from the command line

I'm trying to search a word (from a file) specified in the command line using client/server. Here is my code, however it displays nothing when the client part is run. To run the server, type -s <port number> <file.txt> and for the client, -c localhost <port number> <word to be searched> in the command line.
import java.net.*;
import java.util.*;
import java.io.*;
public class quotes {
public static InetAddress host;
public static ServerSocket serverSocket;
public static String target;
public static void main(String[] args) throws IOException {
if(args[0].equals("-c")){
Client(args);
target = args[3];
}
else if(args[0].equals("-s")){
System.out.println("Server");
Server(args);
}
}
#SuppressWarnings("resource")
public static void Client(String[] args) throws IOException{
String hostname = args[1];
if(hostname.equals("localhost")) host = InetAddress.getLocalHost();
else host = InetAddress.getByName(hostname);
int port = Integer.parseInt(args[2]);
Socket socket = new Socket(host, port);
Scanner input = new Scanner(System.in);
Scanner networkInput = new Scanner(socket.getInputStream());
PrintWriter networkOutput = new PrintWriter(socket.getOutputStream(), true);
Scanner userEntry = new Scanner(System.in);
String response;
networkOutput.println(target);
response = networkInput.nextLine();
while(!response.equals("|")){
System.out.println("\n " + response);
response = networkInput.nextLine();
}
}
public static void Server(String[] args) throws IOException {
int port = Integer.parseInt(args[1]);
String file = args[2];
serverSocket = new ServerSocket(port);
do {
Socket client = serverSocket.accept();
System.out.println("\nNew client accepted.\n");
ClientHandler3 handler = new ClientHandler3(client, file);
handler.start();
}while(true);
}
}
class ClientHandler3 extends Thread {
private Socket client;
private Scanner input;
private PrintWriter output;
private ArrayList<String> quotes;
public ClientHandler3(Socket socket, String file) {
client = socket;
try {
BufferedReader buffer = new BufferedReader(new FileReader(file));
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
String line = reader.readLine();
try {
int ctr = 0;
quotes = new ArrayList<String>();
while(line != null){
quotes.add(ctr, line);
ctr++;
line = buffer.readLine();
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
input = new Scanner(client.getInputStream());
output = new PrintWriter(client.getOutputStream(), true);
}
catch(IOException e) {
e.printStackTrace();
}
}
public void run() {
String target;
String message = "";
target= args[3];
for(int i = 0; i<quotes.size(); i++){
if(quotes.get(i).toUpperCase().contains(target.toUpperCase())){
output.println(quotes.get(i));
}
}
output.println("|");
try {
if (client != null) {
System.out.println("Closing down connection...");
client.close();
}
}
catch(IOException e) {
System.out.println("Unable to disconnect!");
}
}
}
(Thanks to Sir JB Nizet for some modifications and advice) I'm having a problem in target= args[3]; in class ClientHandler3 because I know it makes no sense in overriding. I'm new in this field of programming and I need your help. Please help me figure things out. Thank you!
EDIT
import java.net.*;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.StringTokenizer;
import java.io.*;
public class quotes {
public static InetAddress host;
public static ServerSocket serverSocket;
public static void main(String[] args) throws IOException {
if(args[0].equals("-c")){
Client(args);
}
else if(args[0].equals("-s")){
System.out.println("SERVER KA!!!");
Server(args);
}
}
#SuppressWarnings("resource")
public static void Client(String[] args) throws IOException
String hostname = args[1];
String target, response;
if(hostname.equals("localhost")) host = InetAddress.getLocalHost();
else host = InetAddress.getByName(hostname);
int port = Integer.parseInt(args[2]);
target = args[3];
Socket socket = new Socket(host, port);
Scanner input = new Scanner(System.in);
Scanner networkInput = new Scanner(socket.getInputStream());
PrintWriter networkOutput = new PrintWriter(socket.getOutputStream(), true);
// Set up stream from keyboard entry...
Scanner userEntry = new Scanner(System.in);
networkOutput.println(target);
response = networkInput.nextLine();
while(!response.equals("|")){
// Display server's response to user ...
System.out.println("\n " + response);
response = networkInput.nextLine();
}
}
public static void Server(String[] args) throws IOException {
int port = Integer.parseInt(args[1]);
String file = args[2];
String target = "";
serverSocket = new ServerSocket(port);
do {
// Wait for client...
Socket client = serverSocket.accept();
System.out.println("\nNew client accepted.\n");
ClientHandler3 handler = new ClientHandler3(client, file, target);
handler.start();
}while(true);
}
}
class ClientHandler3 extends Thread {
private Socket client;
private Scanner input;
private PrintWriter output;
private ArrayList<String> quotes;
private String target;
public ClientHandler3(Socket socket, String file, String target) {
// Set up reference to associated socket...
client = socket;
try {
BufferedReader buffer = new BufferedReader(new FileReader(file));
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
this.target = reader.readLine();
String line = reader.readLine();
try {
int ctr = 0;
quotes = new ArrayList<String>();
while(line != null){
quotes.add(ctr, line);
ctr++;
line = buffer.readLine();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
input = new Scanner(client.getInputStream());
output = new PrintWriter(client.getOutputStream(), true);
}
catch(IOException e) {
e.printStackTrace();
}
}
public void run() {
String message = "";
target= input.nextLine();
for(int i = 0; i<quotes.size(); i++){
if(quotes.get(i).toUpperCase().contains(target.toUpperCase())){
output.println(quotes.get(i));
}
}
output.println("|");
try {
if (client != null) {
System.out.println("Closing down connection...");
client.close();
}
}
catch(IOException e) {
System.out.println("Unable to disconnect!");
}
}
}
Set target as a field of ClientHandler3 so you can use it inside run() method.
class ClientHandler3 extends Thread {
...
private String target;
...
and use:
this.target = reader.readLine();
just before
String line = reader.readLine();
line.

Categories