I wrote a simple socket program but the sever is not printing out anything.
Client:
public class ChatClient {
public static void main(String[] args) throws Exception {
Socket socket = new Socket("localhost", 9001);
BufferedReader in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
Scanner reader = new Scanner(System.in);
while (true) {
String test = reader.next();
out.write(test);
System.out.println(test);
//String line = in.readLine();
}
}
}
Server:
public class ServerApplication {
private static final int PORT = 9001;
private static HashSet<String> names = new HashSet<String>();
private static HashSet<PrintWriter> writers = new HashSet<PrintWriter>();
public static void main(String[] args) throws Exception {
ServerSocket listener = new ServerSocket(PORT);
try {
while (true) {
System.out.println("Server starts!");
new ChatThread(listener.accept()).start();
}
} finally {
}
}
}
public class ChatThread extends Thread{
private Socket socket;
private BufferedReader in;
private PrintWriter out;
public ChatThread(Socket socket){
this.socket = socket;
}
#Override
public void run() {
try {
System.out.println("Thread Starts!");
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
while(true){
System.out.println("Getting input!");
String input = in.readLine();
System.out.println("test");
if (input!=null){
//out.print(input);
System.out.println(input);}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Any ideas how should I fix this so when I type "Hello" on client, server will print out "Hello" using system.out.println()?
This is highly likely the socket buffers not being flushed and the data is not actually sent to the socket; the server is waiting for more data before sending a chunk.
If we look at the docs for PrintWriter:
... if automatic flushing is enabled it will be done only when one of the println, printf, or format methods is invoked ...
However, you are using print, not println, so the flushing is not automagic.
Try manualy flushing you streams after writing data:
out.write(test);
out.flush();
yep, this was an answer to a 3 year old post... question was edited and popped up on my stream
Testing your server using telnet (telnet localhost 9001) revealed that it's working just fine. I assume that the fact that it can only print a line at a time, rather than individual characters, is intended behavior.
I did find one bug. When terminating the telnet connection, the server would go into an infinite loop. I suggest the following change:
if (input!=null){
System.out.println(input);}
}
else {
break;
}
For the client, I was able to fix it simply by replacing write with println:
out.println(test);
Related
I basically was trying to give a response back from my server if my client sends me the message "Hello mr server". However it doesn't.
Here is my code :
public class Server {
public static final int PORT = 6666;
public static void main(String[] args) throws IOException {
new Server().runServer();
}
public void runServer() throws IOException {
ServerSocket serverSocket = new ServerSocket(PORT);
System.out.println("Server up and ready for connections.....");
while (true) {
Socket socket = serverSocket.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); //for fetching data
String str = br.readLine(); //for fetching data
System.out.println("Client Data:" + str + '\n');
String dataSendingToClient = "gg";
OutputStreamWriter os = new OutputStreamWriter(socket.getOutputStream()); //for sending data
PrintWriter out = new PrintWriter(os); //for sending data
out.println(dataSendingToClient);
os.flush();
if (br.equals("hey mr server")){
OutputStreamWriter os2 = new OutputStreamWriter(socket.getOutputStream()); //for sending data
PrintWriter out2 = new PrintWriter(os); //for sending data
out2.println("hey mr client");
os.flush();
}
}
}
}
You are using br.equals("hey mr server") which will always return false, since br is not a String, but a BufferedReader
Instead you should use your already defined str variable str.equals("hey mr server")
Also note that with your current code, your server will only read one message from the client before moving on to the next connection
If you want your server to read more messages from a single client, you will need to loop until the client sends a disconnect message/the socket closes
while(true)
{
Socket socket = serverSocket.accept();
BufferedReader br = [...];
PrintWriter out = [...];
for(String message = br.readLine(); message != null; message = br.readLine())
{
//do stuff
//message is each line from the client
}
}
If you have multiple clients trying to connect, you will need to multithread the connections
I would recommend a class to enclose the connection details and use Stacks to poll if the client sent data
public static void main(String[] args) //or whatever other method you're running in
{
List<Connection> clients = new ArrayList<Connection>(); //some data structure to hold the clients
//start accepting connections
new Thread(new Runnable()
{
public void run()
{
while(true)
Connection client = new Connection(serverSocket.accept());
}
}).start();
//do something with the clients, read/write/whatever
}
private class Connection extends Runnable
{
private BufferedReader reader;
private PrintWriter writer;
private Queue<String> messages;
public Connection(Socket s)
{
reader = [...];
writer = [...];
messages = new LinkedList<String>();
}
public void run()
{
//just keep reading
while(true)
messages.add(reader.readLine();
}
public String read()
{
messages.poll();
}
public void write(String msg)
{
writer.write(msg);
writer.flush();
}
}
Note: take that as rough pseudocode
I am trying to build a simple multi client chat application using java sockets. The way I have gone about doing this is by having a client class that connects to a server class that waits for clients to connect and creates a new thread to deal with that client(Where the socket connection is read and written to). The client also reads from and writes to the socket connection to this thread. However, when the client wrote to the output stream of the socket, the server would not respond. A similar question here was posted:
Can you write to a sockets input and output stream at the same time?
One of the answers here says that you can read and write to a socket at the same time as long as reading from the socket is done on a separate thread.
Here is my client application:
public class Client {
Socket socket;
public static void main(String[] args) {
new Client();
}
public Client() {
try {
socket = new Socket("localhost", 4444);
new Thread() {
#Override
public void run() { //read from the input stream
try(
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
) {
String line;
while( (line = in.readLine()) != null ) {
System.out.println("Server said: " + line);
}
} catch(IOException e) {
}
}
}.start();
//write to output stream
try(
PrintWriter out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
Scanner userInput = new Scanner(System.in);
){
System.out.println("Enter Something: ");
if(userInput.hasNextLine()) {
out.println(userInput.nextLine());
}
} catch (IOException e) {
}
} catch(IOException e) {
}
}
}
And my server application:
public class Server {
ServerSocket ss;
public static void main(String[] args) {
new Server();
}
public Server() {
System.out.println("Server Running...");
try {
ss = new ServerSocket(4444);
while(true) {
Socket socket = ss.accept();
new Thread() { //create new thread connection to client
#Override
public void run() {
new Thread() { //thread that reads inputstream
#Override
public void run() {
try(
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
) {
String line;
while( (line = in.readLine()) != null ) {
System.out.println("Client said: " + line);
//The problem seems to lie here.
}
} catch(IOException e) {
}
}
}.start();
//write to outputstream
try (
PrintWriter out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
) {
String sendToClient = "Hey, my name is Server007 B)";
out.println(sendToClient);
} catch(IOException e) {
}
}
}.start();
}
} catch (IOException e) {}
}
}
I will run the server, then run the client, on the client side the output is
Server said: Hey, my name is Server007
Enter something:
Hello! <- enter anything
but the server does not print 'Client said: Hello!' like I expected it to. I hope I made my problem clear enough, thanks.
Ok, so I figured it out, I will answer my own question in case anyone makes the same mistake. The PrintWriter constructor should be this:
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
Not this:
PrintWriter out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
Alternatively, I could have done this:
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
I must have just gotten confused between BufferedWriter and PrintWriter :P
I'm using sockets to chat as part of a large application, however so you can read it easier i have made 2 classes that show the problem. I have a server and a client, the server opens a socket and waits for a client to connect once connected it sends them a welcome message. On the client side they display the welcome message then enter a loop to write to the PrintWriter. On the server side it will now enter a loop that constantly displays text from the bufferedReader however nothing is printing out, not sure if i'm being stupid but think it needs a fresh pair of eyes, Thanks.
public class Server {
public static boolean running = true;
public static PrintWriter out;
public static BufferedReader in;
public static void main(String[] args) throws IOException {
ServerSocket s = new ServerSocket(1932);
while (true) {
Socket cs = s.accept();
out = new PrintWriter(cs.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(cs.getInputStream()));
out.println("Welcome");
out.flush();
while (running == true) {
String input = in.readLine();
if (input.equals("QUIT")) {
System.out.println("theyve gone :( ");
cs.close();
running = false;
} else {
System.out.println(input);
}
}
}
}
}
public class Client {
public static boolean running = true;
public static PrintWriter out;
public static BufferedReader in;
public static Scanner scan;
public static void main (String [] args) throws IOException{
Socket so = new Socket("localhost", 1932);
out = new PrintWriter(so.getOutputStream());
in = new BufferedReader(new InputStreamReader(so.getInputStream()));
System.out.println("TYPE QUIT TO LEAVE ");
System.out.println(in.readLine());
while(true){
scan = new Scanner(System.in);
String message = scan.next();
out.print(message);
out.flush();
}
}
}
In the server, you're reading the next line:
String input = in.readLine();
So the server blocks until the end of line is reached (or the stream is closed).
And on the client, you never send any end of line:
out.print(message);
I have a very simple capitalization Java program. Client sends text read from standard input to server which converts that text into capital letters. Program works well but once client is stopped (NetBeans ide used), server is also reset. Server socket should keep listening for new connection from clients regardless of a client being stopped.
public class Client
{
public static void main(String[] args) throws IOException
{
try(Socket s=new Socket("localhost",9090))
{
while(true)
{
PrintWriter out=new PrintWriter(s.getOutputStream(),true);
BufferedReader rd=new BufferedReader(new InputStreamReader(s.getInputStream()));
BufferedReader from=new BufferedReader(new InputStreamReader(System.in));
String read=from.readLine();
out.println(read);
String answer;
answer=rd.readLine();
System.out.println(answer);
}
}
}
}
public class Server
{
public static void main(String[] args) throws IOException
{
try(ServerSocket listener = new ServerSocket(9090);
Socket socket = listener.accept();)
{
while (true)
{
BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
System.out.println("Started...");
String transform=br.readLine();
String newStr=transform.toUpperCase();
out.println(newStr);
}
}
}
}
What happens is a normal behaviour. You server code only includes handling of a single client. The listener.accept() function only accepts latest connection to server. You need to put the listened.accept() in loop and handle all the exceptions that are raised within. The server-side code should look like this:
public class Server
{
public static void main(String[] args) throws IOException
{
try(ServerSocket listener = new ServerSocket(9090);
while (true) {
try {
Socket socket = listener.accept();)
…
} catch (SocketException ex) {
...
}
}
}
}
But keep in mind that this code will only handle single client at a time. No multi-threading in this code.
Your Server is closing the connection and then finishing becuase it is created outside the while loop. I believe this is what you need.
public class Server {
public static void main (final String[] args)
throws IOException {
while (true) {
try (ServerSocket listener = new ServerSocket(9090); Socket socket = listener.accept();) {
while (true) {
final BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
final PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
System.out.println("Started...");
final String transform = br.readLine();
if (transform == null)
break;
final String newStr = transform.toUpperCase();
out.println(newStr);
}
}
}
}
}
The code works fine when I close the client just after sending one instruction. But when I want a client and server connection to persist, so that the client can send multiple instructions to the server one after another, I get a Null pointer exception at the server and the message java.net.SocketException: Socket is closed at the client. This happens after the client sends a file to the server and the server successfully receives it. Need help. The error occurs at the Connection class code line switch(clientMsg). It seems to me that for some reason the BufferedReader in goes null, but I might be mistaken about that. The code is as follows. Thanks.
Server
public class server {
private static ServerSocket serverSocket;
private static Socket socket = null;
public static void print(Object s) {
System.out.println(s);
}
#SuppressWarnings("resource")
public static void main (String args[]) throws IOException {
System.out.print("Specify listening port: ");
Scanner _a = new Scanner(System.in);
int a = _a.nextInt();
try{
serverSocket = new ServerSocket(a);
}
catch(IOException e) {
System.out.println(e);
}
while (true) {
try {
socket = serverSocket.accept();
print("Connected to " + socket);
Thread client = new Thread(new Connection(socket));
client.start();
}
catch (IOException e) {
print(e);
}
}
}
}
Connection
public class Connection implements Runnable {
public static void print(Object s) {
System.out.println(s);
}
private Socket socket;
private BufferedReader in = null;
public Connection(Socket client) {
this.socket = client;
}
#Override
public void run(){
try {
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
String clientMsg;
while (true) {
clientMsg = in.readLine();
switch (clientMsg) {
case "1":
receiveFile(); //method code not included
break;
default:
print("Command not recognized");
break;
}
//in.close();
}
}//try run()
catch (IOException e) {
print(e);
}
}
Client
public class client {
private static Socket connectToServer;
private static String fileName;
private static BufferedReader keybrdIn;
private static PrintStream msgToServer;
public static void println(Object e) {
System.out.println(e);
}
public static void print(Object e) {
System.out.print(e);
}
public static void main(String args[]) throws IOException{
try{
print("Enter IP: ");
String ip = new Scanner(System.in).nextLine();
print("Enter port: ");
int port = new Scanner(System.in).nextInt();
connectToServer = new Socket(ip, port);
keybrdIn = new BufferedReader(new InputStreamReader(System.in));
}catch(IOException e) {
println(e);
}
msgToServer = new PrintStream(connectToServer.getOutputStream());
while (true) {
try {
switch(Integer.parseInt(action())) { //action() method code not included
case 1:
msgToServer.println("1");
sendFile();
break;
default:
println("Invalid input");
break;
}
}catch (IOException e) {
println(e);
}
}
}
sendFile()
public static void sendFile() throws IOException {
print("Enter file name: ");
fileName = keybrdIn.readLine();
File file = new File(fileName);
byte[] bytearray = new byte[8192];
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
DataInputStream dis = new DataInputStream(bis);
OutputStream os = connectToServer.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
dos.writeUTF(file.getName());
int count;
while ((count = dis.read(bytearray)) > 0){
dos.write(bytearray, 0, count);
}
dis.close();
dos.flush();
dos.close();
}
receiveFile()
public void receiveFile() {
try {
int count;
DataInputStream clientFileStream = new DataInputStream(socket.getInputStream());
String fileName = clientFileStream.readUTF();
OutputStream fileOutput = new FileOutputStream("_" + fileName);
byte[] mybytearray = new byte[8192];
BufferedOutputStream bos = new BufferedOutputStream(fileOutput);
System.out.println("Downloading " + fileName + " ...");
//outToClient().writeBytes("Uploading. Please wait...\n");
while ((count = clientFileStream.read(mybytearray)) > 0){
bos.write(mybytearray, 0, count);
}
fileOutput.close();
bos.close();
clientFileStream.close();
}
catch (IOException e) {
print(e);
}
}
In sendFile(), you close the data output stream which closes your underlying connection's output stream.
According to the documentation of Socket.getOutputStream():
"Closing the returned OutputStream will close the associated socket".
Since you already closed stream, it will also close socket as well as Eyal mentioned. However, at the moment you close the stream, server side will aware of that and return -1 for read() results.
So, even if you didn't specify file length at beginning, this will generally works well.
However, since you already closed stream, you can't reuse it no matter what. To fix this issue, probably you need to change your Client class so that Client should create socket connection, send files, close socket. That's one lifecycle of opened client socket.
Or maybe in while loop of Client class, 1) take ip, port, and filename to send 2) Create new Thread and provide those information so let thread open connection, send file, close connection 3) and in the meantime, client while() can keep take next ip, port, and filename to send from the user. By doing this, you don't need to make client program wait until file transfer to be completed.
Regarding the NPE in the server, readLine() returns null at end of stream. You are ignoring it. You should be testing for it immediately after the call, and if null close the socket and exit the read loop.