I am creating a server app which does the following task
Accept connection from client
Process each client connection to separate thread
Receive data from client
send data to client
I am able to connect client but not able to receive data from client
Data is being visible in my console only when THAT CLIENT GETS DISCONNECTED..!!!
Code :-
public class ServerListener {
public static void main(String[] args) {
new ServerListener().startServer();
}
public void startServer() {
final ExecutorService clientProcessingPool = Executors
.newFixedThreadPool(10);
Runnable serverTask = new Runnable() {
#Override
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(8000);
System.out.println("Waiting for clients to connect...");
while (true) {
Socket clientSocket = serverSocket.accept();
clientProcessingPool
.submit(new ClientTask(clientSocket));
}
} catch (IOException e) {
System.err.println("Unable to process client request");
e.printStackTrace();
}
}
};
Thread serverThread = new Thread(serverTask);
serverThread.start();
}
private class ClientTask implements Runnable {
private final Socket clientSocket;
private ClientTask(Socket clientSocket) {
this.clientSocket = clientSocket;
}
#Override
public void run() {
System.out.println("Got a client !");
try {
/* Get Data From Client */
BufferedReader reader = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
String clientData = "";
clientData = reader.readLine();
System.out.println("Data From Client :" + clientData);
/* Send Data To Client */
//Code
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Problem with your implementation
BufferedReader#readLine:
Reads a line of text. A line is considered to be terminated by any one of a line feed ('\n'), a carriage return ('\r'), or a carriage return followed immediately by a linefeed.
In other words, if your client doesn't ever send \nor \r character that method will not end until the IOException gets thrown as a result of disconnect.
Solution
Replace this code:
BufferedReader reader = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
String clientData = "";
clientData = reader.readLine();
with:
int red = -1;
byte[] buffer = new byte[5*1024]; // a read buffer of 5KiB
byte[] redData;
StringBuilder clientData = new StringBuilder();
String redDataText;
while ((red = clientSocket.getInputStream().read(buffer)) > -1) {
redData = new byte[red];
System.arraycopy(buffer, 0, redData, 0, red);
redDataText = new String(redData,"UTF-8"); // assumption that client sends data UTF-8 encoded
System.out.println("message part recieved:" + redDataText);
clientData.append(redDataText);
}
System.out.println("Data From Client :" + clientData.toString());
InputStream#read:
Reads some number of bytes from the input stream and stores them into the buffer array b. The number of bytes actually read is returned as an integer. This method blocks until input data is available, end of file is detected, or an exception is thrown.
will read as many bytes as it can at the exact moment of its execution - it is basically buffered reading. Since these are raw bytes, when converting them to String you must know its encoding in order to show them correctly (that's the "UTF-8" part). If the encoding in which your client sends bytes is other, you might need to change it in order to get correct text in console output.
I recommend reading the official tutorial lessons:
Byte streams
Character streams
Buffered streams
BufferedReader.readLine() will only return when there's an end-of-line or end-of-stream. Make sure the client side is sending a newline character, or use a different way to read the input stream like:
int ch = 0;
while ((ch = instream.read()) >= 0) {
// do sometyhing with the character off the input stream.
System.out.println("Got byte " + ch);
}
// will get here when the input stream is closed.
Might be an issue with your ExecutorService (not?) being called.
Try to subtitute
clientProcessingPool.submit(new ClientTask(clientSocket));
with
BufferedReader reader = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
String line;
while( (line = reader.readLine()) != null) // just read everything
System.out.println(line);
And see if you get any output at all.
Related
There are two classes in my code:
public class ClientHandler {
private Socket socket;
private DeflaterOutputStream deflaterOutputStream;
private BufferedReader bufferedReader;
public ClientHandler(Socket socket) throws IOException {
this.socket = socket;
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
deflaterOutputStream = new DeflaterOutputStream(socket.getOutputStream());
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < 100000; i++) {
stringBuilder.append(String.format("%d\n", i));
}
deflaterOutputStream.write("start\n".getBytes());
deflaterOutputStream.write(stringBuilder.toString().getBytes());
deflaterOutputStream.write("end\n".getBytes());
deflaterOutputStream.flush();
String dataFromClient = bufferedReader.readLine();
System.out.println(dataFromClient);
}
}
public class Client {
private Socket socket;
private InflaterInputStream inflaterInputStream;
private BufferedReader bufferedReader;
private BufferedWriter bufferedWriter;
public Client(Socket socket) throws IOException{
this.socket = socket;
bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
inflaterInputStream = new InflaterInputStream(socket.getInputStream());
bufferedReader = new BufferedReader(new InputStreamReader(inflaterInputStream));
int receiveCount = 0;
while (socket.isConnected()) {
String messageFromServer;
if ((messageFromServer = bufferedReader.readLine()) != null && messageFromServer.equals("start")) {
while ((messageFromServer = bufferedReader.readLine()) != null && !messageFromServer.equals("end")){
System.out.println(messageFromServer);
}
receiveCount++;
System.out.println("I get " + receiveCount + " times data.");
bufferedWriter.write("I get data.\n");
bufferedWriter.flush();
}
}
}
}
After executing the above code, the terminal of ClientHandler shows nothing, and the terminal of Client shows:
0
1
2
...
98787
98788
So my first question is: Why does the Client only accept 0 to 98788? Where is the remaining numbers after 98788? I am already doing a flush(). In my previous experience, when I use BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); and do bufferedWriter.flush();, it can indeed send all of the data to the Client.
I tried to replace flush() to finish(), and now the Client can receive 0 to 99999 numbers.
So my second question is: What is the difference between flush() and finish()? I have read DeflaterOutputStream, but do not understand what the difference is.
Ok, now, I can send whole data by socket, But I put some code in ClientHandler below:
deflaterOutputStream.write("start\n".getBytes());
deflaterOutputStream.write(stringBuilder.toString().getBytes());
deflaterOutputStream.write("end\n".getBytes());
deflaterOutputStream.finish();
After execute, it throws a exeception: "write beyond end of stream". I can't send data after I do finish().
I thought I could re-declare deflaterOutputStream in this code above. After I add a re-declare of deflaterOutputStream , Client can accept the first part of 0 to 99999, too. But the terminal shows:
0
1
2
...
99998
99999
I get 1 times data.
Client just can accept data before clientHandler does finish() once. This is my third question: How can I send data to client more than once?
I have connection to TCP server (ip,port) to which meter is connected. I'd like to read the specified data from this port because when I'm using standard read method it sends me the whole data stream which takes about 15 minutes to read. So my question: is there any method I can use to get one specified register's value using his OBIS code (1.1.1.8.0.255 - active energy taken) in java via TCP server?
import java.net.*;
import java.io.*;
public class scratch {
public static void main(String[] args) {
String hostname = "ip (hidden)";
int port = port (hidden);
try (Socket socket = new Socket(hostname, port)) {
OutputStream out = socket.getOutputStream();
InputStream input = socket.getInputStream();
InputStreamReader reader = new InputStreamReader(input);
int character;
StringBuilder data = new StringBuilder();
String test = "/?!\r\n";
byte[] req = test.getBytes();
out.write(req);
while ((character = reader.read()) != '\n') {
data.append((char) character);
}
System.out.println(data);
} catch (UnknownHostException ex) {
System.out.println("Server not found: " + ex.getMessage());
} catch (IOException ex) {
System.out.println("I/O error: " + ex.getMessage());
}
}
}
The message "test" send initiation request to meter and his respond is correct but I dont' know how to put flags (ACK STX ETX) in my request, I've tried something like this:
String test2 = (char)0x6 + "051\r\n";
byte[] req2 = test2.getBytes("ASCII");
out.write(req2);
But meter doesn't recognize it.
I have 2 classes (Client and Server) used to implement simple communication in my application. My code is shown below:
Server:
public class Server {
public static void main(String[] ar) {
int port = 1025; // just a random port. make sure you enter something between 1025 and 65535.
try {
ServerSocket ss = new ServerSocket(port); // create a server socket and bind it to the above port number.
System.out.println("Waiting for a client...");
Socket socket = ss.accept();
InputStream sin = socket.getInputStream();
OutputStream sout = socket.getOutputStream();
DataInputStream in = new DataInputStream(sin);
DataOutputStream out = new DataOutputStream(sout);
BufferedReader keyboard = new BufferedReader(new InputStreamReader(
System.in));
System.out.println("enter meter id ");
String line = null;
while (true) {
line = in.readUTF(); // wait for the client to send a line of text.
System.out.println("client send me this id number " + line);
line = keyboard.readLine();
out.writeUTF(line);
out.flush();
//line = in.readUTF();
System.out.println("Waiting for the next line...");
System.out.println();
}
} catch (Exception x) {
x.printStackTrace();
}
}
}
Client:
public class Client {
public static void main(String[] ar) {
int serverPort = 1025;
String address = "localhost";
try {
InetAddress ipAddress = InetAddress.getByName(address); // create an object that represents the above IP address.
System.out.println(" IP address " + address + " and port "
+ serverPort);
Socket socket = new Socket(ipAddress, serverPort); // create a socket with the server's IP address and server's port.
InputStream sin = socket.getInputStream();
OutputStream sout = socket.getOutputStream();
DataInputStream in = new DataInputStream(sin);
DataOutputStream out = new DataOutputStream(sout);
// Create a stream to read from the keyboard.
BufferedReader keyboard = new BufferedReader(new InputStreamReader(
System.in));
String line = null;
System.out.println("ClientConnected.");
System.out.println("enter meter id");
while (true) {
line = keyboard.readLine(); // wait for the user to type in something and press enter.
System.out.println("Sending this number to the server...");
out.writeUTF(line); // send the above line to the server.
out.flush(); // flush the stream to ensure that the data reaches the other end.
line = in.readUTF(); // wait for the server to send a line of text.
System.out
.println("The server was very polite. It sent me this : "
+ line);
System.out.println();
}
}
catch (Exception x) {
x.printStackTrace();
}
}
}
My problem is that while testing the program I do get communication between the client and server, but while debugging, with a break point on the out.flush line in Server.java, it does not go to the intended destination. This intended destination being the line line = in.readUTF(); of Client.java. Can anyone help me to solve this?
It is good practice to open the OutputStreams before the InputStreams, on your sockets, as said in this question.
This question also clarifies that.
What I suspect here is your client and server are running in two different JVM processes and java debugger cannot debug two JVM at the same time.
i have this assignment where i am supposed to write a proxy server that uses java sockets to handle get requests from a client. I am now stuck and have been looking all over google to find the answer but without success.
Christoffers solution helped my with my first problem. Now that i have updated the code this is what i am using.
The problem is that it only downloads parts of most webpages before it gets stuck on sending the packets back to the client loop. At the moment I cant explain why it is behaving the way it is.
public class MyProxyServer {
//Set the portnumber to open socket on
public static final int portNumber = 5555;
public static void main(String[] args){
//create and start the proxy
MyProxyServer myProxyServer = new MyProxyServer();
myProxyServer.start();
}
public void start(){
System.out.println("Starting MyProxyServer ...");
try {
//create the socket
ServerSocket serverSocket = new ServerSocket(MyProxyServer.portNumber);
while(true)
{
//wait for a client to connect
Socket clientSocket = serverSocket.accept();
//create a reader to read the instream
BufferedReader inreader = new BufferedReader( new InputStreamReader(clientSocket.getInputStream(), "ISO-8859-1"));
//string builder for preformance when we loop over the inputstream and read lines
StringBuilder builder = new StringBuilder();
String host = "";
for (String buffer; (buffer = inreader.readLine()) != null;) {
if (buffer.isEmpty()) break;
builder.append(buffer.replaceAll("keep-alive", "close"));
if(buffer.contains("Host"))
{
//parse the host
host = buffer.replaceAll("Host: ", "");
}
System.out.println(buffer);
}
String req = builder.toString();
System.out.println("finshed reading \n" + req);
System.out.println("host: " + host);
//new socket to send the information over
Socket s = new Socket(InetAddress.getByName(host), 80);
//printwriter to send text over the output stream
PrintWriter pw = new PrintWriter(s.getOutputStream());
//send the request from the client
pw.println(req+"\r\n");
pw.flush();
//create inputstream to receive the web page from the host
BufferedInputStream in = new BufferedInputStream(s.getInputStream());
//create outputstream to send the web page to the client
BufferedOutputStream outbuffer = new BufferedOutputStream(clientSocket.getOutputStream());
byte[] bytebuffer = new byte[1024];
int bytesread;
//send the response back to the client
while((bytesread = in.read(bytebuffer)) != -1) {
System.out.println(bytesread);
outbuffer.write(bytebuffer,0, bytesread);
outbuffer.flush();
}
System.out.println("done sending");
//close the streams
inreader.close();
s.close();
pw.close();
outbuffer.close();
in.close();
}
} catch (IOException e) {
e.printStackTrace();
} catch(RuntimeException e){
e.printStackTrace();
}
}
}
If anyone could explain to me why i cant get it working correctly and how to solve it I would be very grateful!
Thanks in advance.
I have a server/client chat room. When the client connects to the server, and sends a message, the client program prints out the message that it sent, but on another client program that is connected to the server, it does not print out until the user presses the 'enter' key.
On the client side:
try {
//Strings to hold messages in and out:
String userinput, serverinput;
//Getting input from the user:
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
//Messages from the server will be printed to the console, messages from console will be sent to the socket:
while(true) {
userinput = input.readLine();
serverout.println(username + "> " + userinput);
serverinput = clientin.readLine();
System.out.println(serverinput);
}
}
On the server side:
public void run() {
PrintWriter output = null;
BufferedReader input = null;
String message;
SchoolRoomServer server = new SchoolRoomServer();;
try {
//i/o for clients:
output = new PrintWriter(socket.getOutputStream());
input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (IOException ioe) {
System.err.println(ioe);
System.exit(1);
}
try {
while((message = input.readLine()) != null) {
server.showAll(message, output);
}
} catch (IOException ioe) {
System.err.println(ioe);
System.err.println("Damn errors.");
System.exit(1);
}
}
By the way- the server.showAll(message, output); method is this:
public void showAll(String msg, PrintWriter printwriter) {
for(int i = 0; i < listWriters.size(); i++) {
if(listWriters.get(i) != printwriter) {
listWriters.get(i).println(msg);
}
}
}
listWriters is an Arraylist of PrintWriters, which gets a PrintWriter associated with a client each time a new thread is made for that client.
So: any ideas on how to immediately print out messages?
Thank you for any help.
You are having the same problem as here. System.in doesn't return anything until the user pressed enter. Then you get the whole line to read.
Read on Socket & ServerSocket
Basically you need to establish a client socket which connects to a server socket then you need to pass the i/o streams between the two to print messages from the client to the server & vice-versa.