For class I am creating a simple client/server. The client opens a jframe, where the user enters the host and port number. If a connection is made, another jframe is opened that has a keylistener. What is typed on the client's side is displayed in the server's jtextarea. I am able to make the connection between client and server, but after this I run into null pointer exception right after. I assume I should be using something else than bufferedreader in my server, or if I could stop the server from reading in until something is actually entered? Or am I doing something else completely wrong? Any help would be appreciated, and the relevant code is below.
public class TypeServer extends JPanel {
BufferedReader lnr;
public TypeServer(Socket soc) throws IOException {
InputStream inStream = soc.getInputStream();
InputStreamReader isr = new InputStreamReader(inStream);
BufferedReader lnr = new BufferedReader(isr);
}
//below is in the main function
try {
ServerSocket srv = new ServerSocket(5555);
Socket soc=srv.accept();
while (true) {
// Create server
TypeServer tc = new TypeServer(soc);
String line=tc.lnr.readLine();
textArea.append(line);
srv.close();
soc.close();
}
}
EDIT: I apologize for not including this before, but the
String line=tc.lnr.readLine();
line hits the null pointer exception
In your main you are using the instance variable
String line=tc.lnr.readLine(); //lnr is not initialized
You have to change the following
BufferedReader lnr = new BufferedReader(isr); //initializing the local variable
to
this.lnr = new BufferedReader(isr);
Related
Method to send message to peer:
public static void writeLineToPeer(Peer peer, String message) throws IOException
{
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(peer.getSocket().getOutputStream(), StandardCharsets.UTF_8));
writer.write(message + "\n");
writer.flush();
}
Reading the response:
public class PeersResponse extends Response<Peer>
{
public PeersResponse(InputStream stream) throws InvalidMessageException, IOException
{
super(stream);
parseResponse();
getNextElement();
}
#Override
protected void parseResponse() throws InvalidMessageException, IOException
{
BufferedReader reader = new BufferedReader(new InputStreamReader(this.stream, "UTF-8"));
setVersion(reader.readLine());
setAmount(reader.readLine());
//Fine until here
}
#Override
public Peer getNextElement() throws InvalidMessageException, IOException
{
BufferedReader reader = new BufferedReader(new InputStreamReader(this.stream, "UTF-8"));
String ip = reader.readLine();
//Socket exception: Socket is closed
if (NetworkHelper.isValidIPAddress(ip))
{
throw new InvalidMessageException();
}
String port = reader.readLine();
String typeOfPeer = reader.readLine();
if (typeOfPeer.length() != 1)
{
throw new InvalidMessageException();
}
try
{
return PeerFactory.getPeer(typeOfPeer.charAt(0), ip, Integer.parseInt(port));
}
catch (Exception ex)
{
throw new InvalidMessageException(ex);
}
}
}
As you can see I get a Socket exception: Socket is closed when trying to read from another instance of a
BufferedReader with the same InputStream.
The message that is being sent is fine and fits the structure of this class.
What's the cause of this? How can I fix this?
The first time you call reader.ReadLine() inside of parseResponse() the BufferedReader reads a chunk of data from the stream. It reads more than just one line, because it does not yet know where the end of line is. The only way for it to read (and remove) just one line from the socket would be to read characters one-by-one and stop when it sees the new line. But that would defeat the purpose of using BufferedReader in the first place.
The second time you call reader.ReadLine() inside of parseResponse(), it does not read from the underlying socket at all. It just parses the data already stored inside BufferedReader and returns the next line.
At the time parseResponse() exits, there is still data stored inside BufferedReader. As the reader variable goes out of scope, that data is lost. It cannot be read from the socket, because it has already been read from the socket.
TLDR;
You can step through parseResponse() in the debugger and look inside the reader instance (examine JDK's internal data structure). You will see your entire message there. And you will see how the remainder of your message gets lost when parseResponse() returns.
Server Side:
try {
ServerSocket server_socket=new ServerSocket(port_number);
Socket client_socket= server_socket.accept();
PrintWriter output = new PrintWriter(client_socket.getOutputStream(),true);
BufferedReader input = new BufferedReader(new InputStreamReader(client_socket.getInputStream()));
BufferedReader stdIn=new BufferedReader(new InputStreamReader(System.in));
String userInput, clientOutput;
while ((userInput=stdIn.readLine())!="EXIT") {
if ((clientOutput=input.readLine())!=null) {
System.out.println("Client: "+clientOutput);
} if (userInput!=null) {
output.println(userInput);
output.flush();
}
}
}
Client Side:
try {
Socket client_socket= new Socket(hostname,port_number);
PrintWriter output = new PrintWriter(client_socket.getOutputStream(),true);
BufferedReader input = new BufferedReader(new InputStreamReader(client_socket.getInputStream()));
BufferedReader stdIn=new BufferedReader(new InputStreamReader(System.in));
String userInput,serverOutput;
while ((userInput=stdIn.readLine())!="EXIT") {
if ((serverOutput=input.readLine())!=null) {
System.out.println("Server: "+serverOutput);
} if (userInput!=null) {
output.println(userInput);
output.flush();
}
}
}
The code in my case makes sense to me, I cant seem to figure out why an enter still needs to be pressed, does it have something to do with .readLine()?
I checked out the following post Server Client in Java only displays message when I press enter, however the solution provided does not fix the situation.
Note: Initially there were no if statements in the while loop. The way I saw this to be an issue was that the while loop may get stuck on one of the lines, waiting for user/server input. Therefore implementing if statements allowed it to skip the waiting portion and re-run the loop.
Turns out I mixed my variables up.
The while loops should be:
while ((userInput=input.readLine())!="EXIT") {
It fixed it, but there are some other issues still present
does it have something to do with .getLine()?
Yes. If you look at the Javadoc for BufferedReader#readLine(), it clearly states that an end of line character terminates the String to be read:
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.
I have the following code. It seems that I am streaming the content accurately. However, the image is not being captured correctly. I am new to Java. Basically, I am a C, C++, linux programmer. I am wondering that the problem is reading the buffer line by line. Am I missing something here?
Here is the socket server code -
import java.io.*;
import java.net.*;
public class ImageSocketServer {
public static void main(String args[]) throws IOException
{
ImageSocketServer imageServer = new ImageSocketServer();
imageServer.run();
}
private void run() throws IOException {
// TODO Auto-generated method stub
ServerSocket serverSock = new ServerSocket(1025);
Socket sock = serverSock.accept();
InputStream imagetoShare = new BufferedInputStream(new FileInputStream("/export/home/joshis1/Lizard.png"));
PrintStream imageSend = new PrintStream( sock.getOutputStream());
imageSend.print(imagetoShare);
}
}
Here is the socket client code -
import java.io.*;
import java.net.*;
public class ImageSocketClient {
public static void main(String args[]) throws IOException
{
ImageSocketClient imageClient = new ImageSocketClient();
ImageSocketClient.run();
}
private static void run() throws UnknownHostException, IOException
{
// TODO Auto-generated method stub
BufferedWriter bufWriter = null;
bufWriter = new BufferedWriter(new FileWriter(
"/export/home/joshis1/file1.png"));
Socket sock = new Socket("localhost", 1025);
InputStreamReader IR = new InputStreamReader(sock.getInputStream());
BufferedReader BR = new BufferedReader(IR);
String data;
while ((data = BR.readLine()) != null)
{
System.out.println("Shreyas got the data");
bufWriter.write(data);
}
bufWriter.close();
}
}
I see that the source image is of size -
$ ls -l Lizard.png
-rw-rw-r-- 1 joshis1 joshis1 19071522 May 29 15:46 Lizard.png
and the destination image is wrongly copied -
$ ls -l file1.png
-rw-rw-r-- 1 joshis1 joshis1 34 May 29 17:38 file1.png
First of all your imageSend.print(imagetoShare); sends over the String representation of an InputStream, which explains the small content of the file. You'll want to create a loop that reads from imagetoShare (although you might want to name it better, it's not an image, it's a stream) and writes the data to the outputstream (search around for the quintessential read-write loop).
Secondly, you're using PrintStream which is used to write character data to an OutputStream. You want to use a BufferedOutputStream for that.
There's a variety of errors in your code due to wrong use of the various java.io-classes.
1.) You are using PrintStream's print(Object o) method. This is not copying the stream's content but is just writing a textual representation of the object.
2.) In your client you are using Reader and Writer classes. These are used to handle character-data while your images are raw binary data. You'll get into lots of trouble considering encoding, non-printable characters etc. this way.
To wrap it up: Use plain BufferedInputStreams and BufferedOutputStreams to do your input and output. You'll have to wrap it all up in some loops because you'll only be reading a bunch of bytes at a time.
The application is a basic chat client.
I got a Thread for getting data from the server.
I want to get every response from the server separately.
It prints in the console only when the loop breaks (when i send "exit" using the other parts of the application).
So when "System.out.println" responds it prints the whole buffer at once.
How can i make it work and print every response separately?
Thank you!
EDIT!!
The server respond should include "\n" after each line,
it works for me in this way.
Without "\n" it just waits until the loop breaks.
Is there a better way to do this without the "\n" issue?
class ServerThread implements Runnable {
#Override
public void run(){
BufferedReader in = null;
Socket socket;
try
{
if (Thread.currentThread().isAlive()) {
sendString("exit");
Thread.currentThread().interrupt();}
InetAddress serverAddress = InetAddress.getByName(SERVER_IP);
socket = new Socket(serverAddress, SERVER_PORT);
outr = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String serverResponse;
while((serverResponse = in.readLine()) != null)
{
System.out.println(serverResponse);
}
in.close();
outr.close();
socket.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
You're using a BufferedReader and read it with in.readLine(), which, surprise surprise, will return the next line in the response. A line is a string terminated by a newline character, so your BufferedReader will have to wait until it sees a newline until it can return your line. If you don't want to use newlines in your response, don't use readLine(), use one of the other read() methods instead.
I'm trying to make a Java TCP client and a node.js TCP server talk together.
This is my code at the moment :
The Java client
import java.net.;
import java.io.;
public class Client2{
public static void main(String[] args) throws Exception{
Socket s = new Socket("192.168.1.35",8500);
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
dos.writeUTF("abcdefgh");
dos.close();
s.close();
}
}
the Node.js Server
var net = require('net'),
server = net.createServer();
server.on('connection', function (client) {
console.log('Hello World !');
client.on('data', function(data) {
var message = data.toString('utf8');
console.log('***' + message +'***');
});
});
server.listen(8500);
This example will give this result back :
Hello World !
**abcdefgh***
but with this as input :
abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
it gives this back :
Hello World !
***�abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz***
with this input :
qq32we3w87d 38s1d87s4df7s4d1+s2d7f+sfdsf4sà$àà3663%ç%&ç%&ç
it gives this back :
Hello World !
***#qq32we3w87d 38s1d87s4df7s4d1+s2d7f+sfdsf4sà$àà3663%ç%&ç%&ç***
tldr: Sometimes when logging the buffers, node adds characters (rectangles with numbers or ?) at the beginning or event cuts some characters at the start out.
- How can I log buffers and assign them to a variable the right way ?
I'm not an expert on DataOutputStream, but if it really is adding extra characters, you should use something else.
When I did server stuff, I used BufferedReader and BufferedWriter. It looks like this:
Socket s = new Socket(<<WEB ADDRESS AS STRING>>,<<PORT NO AS INT>>);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
//left out a bunch of lines. This is where you should read the lines
//of input (with an inner loop) and send stuff back
s.shutdownInput();
bw.flush();
s.shutdownOutput();
NOTE, IF YOU'RE GOING TO DEAL WITH LARGE PAGES, THIS COULD CAUSE A PROBLEM, AS THE BUFFEREDREADER AND BUFFEREDWRITER WILL FILL UP BEFORE YOU'RE READY. if this is a problem I'd look into the other Reader and Writer classes. They are quite plentiful, as I understand it, and one should suit your needs.