I am trying to implement a java command line chat server and client. I am using 4 classes, the Server.java sets up a ServerSocket and accepts all connections. The Client.java can connect to the Server, then 2 threads for both client and server are created using the SendMessages.java and ReceiveMessages.java. The threads are responsible for taking the input from stdin and sending it to the output stream of the socket, and taking the incoming input stream to print it to stdout. Everything works when launching the server and connecting the client, the chat also works. However, when either client or server is terminated a resource leak is caused. I want the SendMessages class and ReceiveMessages class to be able to detect when the connection of client or server is terminated and close all resources to avoid resource leaks. Here is the code:
Server.java
import java.net.*;
import java.io.*;
import java.util.*;
public class Server{
public static void main(String[] args) throws SocketException,IOException{
ServerSocket s = new ServerSocket(8000);
s.setSoTimeout(10000000);
while(true){
Socket clientSocket = s.accept();
handle(clientSocket);
}
}
static void handle(Socket clientSocket) throws IOException{
System.out.println("connection accepted from " + clientSocket.getRemoteSocketAddress());
receiveMessages(clientSocket);
sendMessages(clientSocket);
}
static void receiveMessages(Socket clientSocket) throws IOException{
(new Thread(new ReceiveMessages(clientSocket))).start();;
}
static void sendMessages(Socket clientSocket)throws IOException{
(new Thread(new SendMessages(clientSocket))).start();
}
}
Client.java
import java.net.*;
import java.io.*;
import java.util.*;
public class Client{
public static void main(String[] args) throws IOException, UnknownHostException, ConnectException{
String hostname = args[0];
int port = Integer.parseInt(args[1]);
Socket s = null;
s = connect(hostname, port);
handle(s);
}
public static Socket connect(String hostname, int port) throws UnknownHostException, IOException, ConnectException{
Socket s = null;
try{
s = new Socket(hostname, port);
} catch(ConnectException e){
System.out.println("Connect Exception caught!");
}
return s;
}
static void handle(Socket clientSocket) throws IOException, UnknownHostException{
receiveMessages(clientSocket);
sendMessages(clientSocket);
}
static void receiveMessages(Socket clientSocket) throws IOException, NullPointerException{
(new Thread(new ReceiveMessages(clientSocket))).start();
}
static void sendMessages(Socket clientSocket)throws IOException, NullPointerException{
(new Thread(new SendMessages(clientSocket))).start();
}
}
SendMessages.java
import java.io.*;
import java.net.*;
import java.util.*;
public class SendMessages implements Runnable{
Socket clientSocket;
public SendMessages(Socket clientSocket){
this.clientSocket = clientSocket;
}
public void run(){
System.out.println("SendMessages thread has started.");
Scanner sc = new Scanner(System.in);
PrintWriter out = null;
try{
out = new PrintWriter(clientSocket.getOutputStream(), true);
}
catch(IOException | NullPointerException e){}
String message;
while(true){
message = sc.nextLine();
out.println(message);
if(out.checkError()){
out.close();
sc.close();
System.out.println("SendMessages closed");
}
}
}
}
ReceiveMessages.java
import java.io.*;
import java.net.*;
import java.util.*;
public class ReceiveMessages implements Runnable{
Socket clientSocket;
public ReceiveMessages(Socket clientSocket){
this.clientSocket = clientSocket;
}
public void run(){
System.out.println("ReceiveMessages thread has started.");
BufferedReader in = null;
try{
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
}catch(IOException|NullPointerException e){}
String message;
try{
while(true){
while((message = in.readLine())!= null){
System.out.println(message);
}
}
} catch(IOException|NullPointerException e){
System.out.println("ReceiveMessages resources closed.");
try{
in.close();
clientSocket.close();
}
catch(IOException f){}
}
}
}
Thank you!
So I have recently delt myself with such an issue.
The problem is, that by shutting one side of the connection down, a "half-open" connection remains (which isn't a real connection anymore).
The Socket API does not have an option to check, if the partnered service/device is still alive.
So what to do about that? I myself prefer the concept of heartbeats.
Every 10 seconds (or any other timeframe, it's up to you) a heartbeat is send to the output stream of the socket. This operation throws a IOException, when the stream is no longer avaiable. Therefore you can catch the the exception and handle all "close" operations within the catch block.
Example:
public class Heartbeater
implements Runnable
{
private OutputStream os;
private ServerHandler servhand;
private Logger logger = Logger.getLogger( Logger.GLOBAL_LOGGER_NAME );
//NOTE: ServerHandler is my class which handles the socket of the server after ServerSocket.accept();
public Heartbeater( OutputStream os, ServerHandler servhand )
{
this.servhand = servhand;
this.os = os;
}
#Override
public void run()
{
try
{
Thread.currentThread().setName( "Heartbeater" );
// while the handler's connection is alive
while ( servhand.isConnectionAlive() )
{
Thread.sleep( 10000 );
// dummy write to trigger the exception if the client does not respond properly
os.write( "_HEARTBEAT_".getBytes() );
}
}
catch ( InterruptedException e )
{
logger.log( Level.SEVERE, "HEARTBEATER GOT INTERRUPTED", e );
Thread.currentThread().interrupt();
}
catch ( IOException e )
{
logger.log( Level.INFO, "The connection to the client has been lost." );
// Here you would define the resource close operation.
servhand.setConnectionAlive( false );
}
}
}
Related
I have got a problem setting up a server - client connection for a robot in java.
I have got two clients listening to two different ports. When the server is sending an error is occurring the PrintWriter is null.
Perhaps the methods are in two different instances. But how can I fix that?
Server code:
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
// port for the TCP/IP network
private static int port = 30001;
public void setPort(int newPort) {
port = newPort;
}
private ServerSocket serverSocket;
private Socket socket;
private PrintWriter pw;
public void start() throws IOException {
System.out.println("Server: Hi, I am ready to serve you!");
System.out.println("Server: Trying to connect.");
// get a connection
try {
serverSocket = new ServerSocket(port);
socket = serverSocket.accept();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Server: I got a connection!");
pw = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
}
public void sendString(String msg) {
pw.println(msg);
pw.flush();
}
public void stop() throws IOException {
pw.close();
socket.close();
serverSocket.close();
System.out.println("Server has stopped");
}
}
Code of the coordinating class:
package ServerV4Test;
import java.io.IOException;
public class CoordinateServer {
private Server myServer01 = new Server();
private Server myServer02 = new Server();
public void sendString(String msg) {
myServer01.sendString(msg);
myServer02.sendString(msg);
}
public void startServerMaster () throws IOException {
System.out.println("The server coordinator started!");
Server myServer01 = new Server();
myServer01.setPort(30001);
myServer01.start();
Server myServer02 = new Server();
myServer02.setPort(30002);
myServer02.start();
}
}
Programm code:
import java.io.IOException;
public class ProgramServer {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
CoordinateServer coordServer = new CoordinateServer();
coordServer.startServerMaster();
String sendString = "hello world";
coordServer.sendString(sendString);
coordServer.closeServerMaster();
}
}
Error message:
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.io.PrintWriter.println(String)" because "this.pw" is null
at ServerV4Test.Server.sendString(Server.java:40)
at ServerV4Test.CoordinateServer.sendString(CoordinateServer.java:11)
at ServerV4Test.ProgramServer.main(ProgramServer.java:16)
Client code:
import java.io.*;
import java.net.*;
import java.util.ArrayList;
public class Client {
// set port and IP for the server
private String hostname = "localhost";
private int port;
public void setHostname (String sHost) {
hostname = sHost;
}
public void setPort(int sPort) {
port = sPort;
}
private InetSocketAddress address;
private void createAddress() {
address = new InetSocketAddress(hostname, port);
}
// create a list for the received strings
private ArrayList<String> receivedList= new ArrayList<String>();
public String getReceivedString() {
String temp = receivedList.get(0);
receivedList.remove(0);
return temp;
}
public boolean hasReceivedString() throws IOException {
receiveString();
if (receivedList.size() > 0) {
return true;
}
else {
return false;
}
}
private Socket socket;
private BufferedReader bufReader;
public void start() throws IOException {
System.out.println("Client: I start myself!");
System.out.println("Client: creating connection!");
socket = new Socket();
createAddress();
socket.connect(address);
System.out.println("Client: I got a connection!");
InputStreamReader iStreamReader = new InputStreamReader(socket.getInputStream());
bufReader = new BufferedReader(iStreamReader);
}
private void receiveString() throws IOException {
while (bufReader.ready()) {
if(bufReader.ready()) {
String message = bufReader.readLine();
receivedList.add(message);
}
}
}
public void stop() throws IOException {
bufReader.close();
socket.close();
System.out.println("Client has stopped");
}
}
Client programm:
import java.io.IOException;
public class ProgramUseClient1 {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
System.out.println("client testprogram started");
// create an instance of the server
Client myClient = new Client();
myClient.setPort(30001);
// start client
myClient.start();
// repeat receiving and sending
boolean progRunning = true;
while(progRunning) {
// test if something is received
if(myClient.hasReceivedString()) {
String receivedString = myClient.getReceivedString();
System.out.println("The client 1 received: " + receivedString);
// test if client should be stopped
myClient.stop();
progRunning = false;
}
}
System.out.println("Goodbye");
}
}
You have created shadowed variables myServer01 and myServer02 where the global variables do not have PrintWriter pw initialized. Replace
Server myServer01 = new Server();
with
myServer01 = new Server();
and similarly for myServer02
It is all about timing of events...
When you instantiate a Server object, the global variable pw is null. It is not until Server#start() is called that the writer is properly instantiated. Unfortunately for you, the CoordiateServer calls sendString before the Server objects are running (start() is never called).
There is no reason why you need to delay the creation of the PrintWriter. Make sure it is instantiated in the Server constructor.
I have a server that accepts sockets from whenever a client connects. I want to be able to shutdown my local server and let my client try to reconnect for about 5 times, and if I start my server the client should indicate that you have reconnected again.
I understand somewhat that this is done in the try{} catch(IOException){Here goes the code for handleing reconnect} I want to use the same socket that I first used to connect. I don't want to create a new Client cause then I have to enter username and stuff like that all over again
I tried to creating a new socket like clientSocket = new Socket("localhost", portnr) but I don't know if this is the correct way to go. If you have examples that answers this please link them. I dont mind reading as long as it is good documented. Thanks in advance!
EDIT.
Here is my Client Class
public class Client {
public static void main(String[] args) {
Client client = new Client();
client.connect();
}
//------------------------------------------------------------
//METHOD CONNECT
//------------------------------------------------------------
private void connect(){
int reConnectTries = 0;
Socket clientsocket;
try {
//------------------------------------------------
//Sets up variables needded for execution
clientsocket = new Socket("localhost", 8900);
DataOutputStream OUT = new DataOutputStream(clientsocket.getOutputStream());
ListenforMessages listen = new ListenforMessages(clientsocket);
//We don't want to enter username all the time
//So this goes not in the while-loop
//------------------------------------------------
Scanner keyboard = new Scanner(System.in);
System.out.println("Enter username");
String username = keyboard.nextLine();
//Sends username to sever so it can be added to a list
OUT.writeUTF(username);
//------------------------------------------------
//------------------------------
//Creates a thread to listen on messages from server(Other clients in this case)
Thread trd = new Thread(listen);
trd.start();
//------------------------------
while (true) {
try {
String sendMessage = keyboard.nextLine();
OUT.writeUTF(sendMessage);
OUT.flush();
} catch (Exception e) {
System.err.println("Could not send message to server. " + e);
}
}
} catch (IOException e) {
System.err.println("Couldnt establish a connection: " + e);
}
}
//------------------------------------------------------------
//CLASS FOR HANDLEING INPUT. We create a class for input on a new thread
//This is cause we don't want it to block other processes.
//----------------------------------------------------------------
class ListenforMessages implements Runnable{
Socket mySocket;
DataInputStream IN;
public ListenforMessages(Socket X) throws IOException {
this.mySocket = X;
}
#Override
public void run() {
try {
IN = new DataInputStream(mySocket.getInputStream());
while (true) {
System.out.println(IN.readUTF());
}
} catch (Exception e) {
System.err.println("Couldn't fetch message from server.Error: " + e);
}
}
}
}
There's a couple of solutions to this problem, but a simple one would to be have the client try to reconnect (open a new connection to the server) at set intervals. For example, you could try something like this to have your client try to reconnect once every 3 minutes:
while(true) {
try {
clientSocket = new Socket("localhost", portnr);
break; // We connected! Exit the loop.
} catch(IOException e) {
// Reconnect failed, wait.
try {
TimeUnit.MINUTES.sleep(3);
} catch(InterruptedException ie) {
// Interrupted.
}
}
}
This way, the client will try to connect, and if it fails, wait for 3 minutes before trying again.
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.NoRouteToHostException;
import java.net.SocketAddress;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.net.ConnectException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.InputStream;
import java.io.DataOutputStream;
import java.io.DataInputStream;
import java.util.Scanner;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
final class TCPClient{
private static Scanner in ;
private static DataOutputStream douts;
private static OutputStream outs;
private static InputStream ins;
private static DataInputStream dins;
private static String ip;
private static Integer port;
private int count = 0;
private static int times;
public TCPClient(){
serverConTest(port);
}
private boolean portIsOpenOrNot(String ip, int port){
try{
Socket socket = new Socket();
socket.connect(new InetSocketAddress(ip,port),500);
socket.close();
return true;
}catch(Exception e){
}
return false;
}
private void serverConTest(int port){
while(true){
try{
InetAddress addr = InetAddress.getByName(ip);
SocketAddress sockaddr = new InetSocketAddress(addr,port);
Socket socket = new Socket();
System.out.println("Connecting To server...");
socket.connect(sockaddr);
Thread.sleep(1000);
boolean isactive = true;
if(portIsOpenOrNot(ip,port)){
outs = socket.getOutputStream();
douts = new DataOutputStream(outs);
System.out.println("Sending Request to server:");
while(isactive){
Thread.sleep(1000);
douts.writeUTF("Are you Alive..!");
ins = socket.getInputStream();
dins = new DataInputStream(ins);
System.out.println("Response from server : "+dins.readUTF());
}
}
}catch(SocketException e){
System.out.println("Connection lost");
}catch(IOException e){
break;
}catch(InterruptedException e){
System.out.print("connection timeout in 50 second.");
break;
}
}
}
public static void main(String[] args){
in = new Scanner(System.in);
System.out.print("Enter ip : ");
ip = in.nextLine();
System.out.print("Enter Port : ");
port = Integer.parseInt(in.next());
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future future = executorService.submit(new Runnable() {
public void run() {
new TCPClient();
}
});
try{
future.get(50, TimeUnit.SECONDS);
}catch(InterruptedException e){
}catch(ExecutionException e){
}catch(TimeoutException e){
executorService.shutdownNow();
}
}
}
This sample will give you the complete understanding that when the server restarts then client will reconnects.
I didnt read all your code but this one is working for me
And dont forget to add the Server class and the method send that sends messages...
Client :
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
public class Client {
static Socket sock=null;
static DataInputStream in=null;
static DataOutputStream out=null;
static boolean connected=false;
static String currentip="";
static int currentport=0;
static void refreching(){
try {
in=new DataInputStream(sock.getInputStream());
out=new DataOutputStream(sock.getOutputStream());
Thread gg=new Thread() {
String msg="";
public void run() {
while(connected) {
try {
msg=in.readUTF();
System.out.println(msg);
} catch (IOException e) {
connected=false;
System.out.println("Reconnecing...");
while(!connected)
connect(currentip,currentport);
}
}
}
};
gg.start();
}
catch(Exception e) {
System.out.println("Problem while reading incoming and outgoing"+
"messages!");
connected=false;
}
}
static void connect(String iphost, int port){
try{
sock=new Socket(iphost,port);
currentip=iphost;
currentport=port;
connected=true;
refreching();
System.out.println("Connected!");
}
catch(Exception e){
System.out.println("Cant connect !");
connected=false;
}
}
public static void main(String[] args) {
connect("127.0.0.1",1234); //Example you can enter another's computer ip
//adress if connected to the same network !!!
//Send(Message_To_Server); Dont forget to add the sending code!!!
//Maybe i'll upload a video one day==>how to create a chat application
}
I want to made a Server Which makes a client and start conversation with him but IOException is occur in Handler's code I couldn't underStand why Br.readLine method throws Exception
Here is code of mine Server project's package's classess and two clients abc, def classes are also
This is code of Server projects classeess...............
package server;
import java.io.IOException;
import java.net.ServerSocket;
public class Server {
private void operate() {
try {
ServerSocket serverSocket = new ServerSocket(2222);
while(true) new Thread(new Handler(serverSocket.accept())).start();
} catch(IOException e){
System.out.println("IOException in operate method of Server");
}
}
public static void main(String[] args) {
new Server().operate();
}
}
package server;
import java.io.*;
import java.net.Socket;
public class Handler implements Runnable {
Handler(Socket s) {
socket = s;
counter++;
}
public void run() {
try {
while(true) System.out.println(new BufferedReader(new InputStreamReader(socket.getInputStream())).readLine()); //This throw the IOExceptionnnnnnnnnnnnnnnnnnnnn...............
} catch(IOException e) {
System.out.println("IOException in "+counter+"'s run method");
}
}
private final Socket socket;
private static int counter =0;
}
Code of First Client ABC...........................
package abc;
import java.net.Socket;
import java.io.*;
public class Abc {
public static void main(String[] args) {
try {
Socket socket = new Socket("localhost",2222);
while(true) new PrintWriter(socket.getOutputStream()).println("HI from Abc");
} catch(IOException e) {
System.out.println("IOException in main ");
}
}
}
Code of Another Client DEf.........................
package def;
import java.io.*;
import java.net.Socket;
public class DEf {
public static void main(String[] args) {
try {
Socket socket = new Socket("localhost",2222);
while(true) new PrintWriter(socket.getOutputStream()).println("HI from Abc");
} catch(IOException e) {
System.out.println("IOException in main ");
}
}
}
Your clients request the output stream repeatedly from the socket using socket.getOutputStream(). Instead, you should invoke this method and create a corresponding writer only once, for example:
Socket socket = new Socket("localhost",2222);
PrintWriter writer = new PrintWriter(socket.getOutputStream());
while(true) {
writer.println("HI from Abc");
...
}
Same with the Handler class - create your buffered reader once.
I have already posted answers on Server-Client Socket Communication. Please have a look.
Java Server with Multiclient communication.
Basic echo server, client-server relationship
Try this code. It might solve you problem.
Handler.java:
Check BufferedReader.ready() before BufferedReader.readLine()
Use single BufferedReader
class Handler implements Runnable {
private BufferedReader reader;
Handler(Socket s) {
socket = s;
counter++;
try {
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
try {
while (socket.isConnected() && !socket.isClosed()) {
if(!reader.ready()){
continue;
}
//System.out.println("ready");
System.out.println(reader.readLine()); // This throw
// the
} // IOExceptionnnnnnnnnnnnnnnnnnnnn...............
} catch (Exception e) {
e.printStackTrace();
System.out.println("IOException in " + counter + "'s run method");
}
}
private final Socket socket;
private static int counter = 0;
}
Abc.java:
Use single PrintWriter
PrintWriter writer = new PrintWriter(socket.getOutputStream());
while (true)
writer.println("HI from Abc");
DEf.java:
Use single PrintWriter
PrintWriter writer = new PrintWriter(socket.getOutputStream());
while (true)
writer.println("HI from Abc");
i am creating a LAN game that accepts strings and parses them from structured english and displays them on a grid. i have created the server and client and it works but im having some issues. when i send a string it doesnt appear on the other machine right away. for some reason the string is only sent to the other machine once the other machine sends something over. i dont know why this happens. Could you please help me find out why it doesnt send straight away. Thanks
Server Code:
import java.awt.Point;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
public class studentServer{
static ServerSocket serverSocket;
static Socket socket;
static PrintWriter printWriter;
static BufferedReader bufferedReader;
static Thread thread;
Console console = new Console();
public ServerPlayergameMain gm;
public static void main(String args[]) throws Exception{
}
public void run(String commandMessage){
while(true){
try{
printWriter.println(commandMessage+"\n");
String input = bufferedReader.readLine();//reads the input from textfield
console.readLine("Client message: "+input);//Append to TextArea
}catch(Exception e){}
}
}
public void serverStartActionPerformed() {
System.out.println("Server has started!");
try{
serverSocket = new ServerSocket (8888); // socket for the server
socket = serverSocket.accept(); // waiting for socket to accept client
JOptionPane.showMessageDialog(null, "Your opponent has connected!", "Opponent Connection!", JOptionPane.INFORMATION_MESSAGE);
gm = new ServerPlayergameMain();
gm.setVisible(true);
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); // reads line from input streamer
printWriter = new PrintWriter(socket.getOutputStream(),true);
}catch(IOException | HeadlessException e){
System.out.println("Server not running!"); //print message if server is not running
}
}
}
Client Code:
import java.io.*;
import java.net.*;
import javax.swing.JOptionPane;
public class StudentClient {
static Socket socket;
static PrintWriter printWriter;
static BufferedReader bufferedReader;
static Thread thread;
Console console = new Console();
public ClientPlayergameMain gm;
public void Clients(String address) {
try{
socket=new Socket("localhost",8888);//Socket for client
//below line reads input from InputStreamReader
bufferedReader=new BufferedReader(new InputStreamReader(socket.getInputStream()));
//below line writes output to OutPutStream
printWriter=new PrintWriter(socket.getOutputStream(),true);
JOptionPane.showMessageDialog(null, "Connected to server successfully", "Success", JOptionPane.INFORMATION_MESSAGE);
gm = new ClientPlayergameMain();
gm.setVisible(true);
System.out.println("Connected");//debug code
}catch(Exception e){
JOptionPane.showMessageDialog(null, "No Connection to server", "Error", JOptionPane.ERROR_MESSAGE);
System.out.println("Not Connected");
}
}
public static void run(String commandMessage){
while(true){
try{
printWriter.println(commandMessage+"\n");
String input = bufferedReader.readLine();
System.out.println("From server:" +input);
}catch(Exception e) {}
}
}
}
The code works but i dont know why there is a condition for the other machine to send something.
Thanks for your time.
A lot of compilation problems are there in you code. Some of the classes and objects are missing to resolve.
Still I have tried it to figure out the issue.
It may be the reasons:
sending new line character \n in printWriter.println(commandMessage+"\n"); statement, just remove \n.
client and server both are writing first in printWriter.println(commandMessage+"\n"); statement, make it last in anyone class
Here is the code:
StudentServer.java:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class StudentServer {
static ServerSocket serverSocket;
static Socket socket;
static PrintWriter printWriter;
static BufferedReader bufferedReader;
static Thread thread;
public static void main(String args[]) throws Exception {
StudentServer studentServer = new StudentServer();
studentServer.serverStartActionPerformed();
studentServer.run("server");
}
public void run(String commandMessage) {
if (true) {
try {
printWriter.println(commandMessage);
String input = bufferedReader.readLine();// reads the input from textfield
System.out.println("Client message: " + input);// Append to TextArea
} catch (Exception e) {
}
}
}
public void serverStartActionPerformed() {
System.out.println("Server has started!");
try {
serverSocket = new ServerSocket(8888); // socket for the server
socket = serverSocket.accept(); // waiting for socket to accept client
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); // reads
// line
// from
// input
// streamer
printWriter = new PrintWriter(socket.getOutputStream(), true);
} catch (Exception e) {
e.printStackTrace();
System.out.println("Server not running!"); // print message if server is not running
}
}
}
StudentClient.java:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class StudentClient {
static Socket socket;
static PrintWriter printWriter;
static BufferedReader bufferedReader;
static Thread thread;
public void clients() {
try {
socket = new Socket("localhost", 8888);// Socket for client
// below line reads input from InputStreamReader
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// below line writes output to OutPutStream
printWriter = new PrintWriter(socket.getOutputStream(), true);
System.out.println("Connected");// debug code
} catch (Exception e) {
System.out.println("Not Connected");
}
}
public void run(String commandMessage) {
if (true) {
try {
String input = bufferedReader.readLine();
System.out.println("From server:" + input);
printWriter.println(commandMessage);
} catch (Exception e) {
}
}
}
public static void main(String args[]) throws Exception {
StudentClient studentClient = new StudentClient();
studentClient.clients();
studentClient.run("client");
}
}
Have you tried printWriter.flush() after each write/print?
There are quite a few little problems, as Braj points out. The main one is in this sequence on your server side:
serverSocket = new ServerSocket (8888); // socket for the server
socket = serverSocket.accept(); // BLOCKS waiting for socket to accept client
// ..
printWriter = new PrintWriter(socket.getOutputStream(),true);
This means that printWriter, which you use to write to the client, doesn't even exist until after the server has listened for, blocked waiting on, and accepted a connection from the client.
If you want the connection to be opened for reading and writing without seeming to send anything from the client, send a handshake from the client. You could copy SMTP, and use HELO <myname>. That even tells the server who's calling.
Update after further reading:
I've always done like you have, and used the implicit connect that happens when you use getOutputStream() on the client side. However, Socket does allow you to connect an existing socket manually, using Socket#connect(). Try that, maybe it will work better than a handshake, for you.
basically what i want to do is develop a chat program(something between an instant messenger and IRC) to improve my java skills.
But I ran into 1 big problem so far: I have no idea how to set up streams properly if there is more than one client. 1:1 chat between the client and the server works easily, but I just don't know what todo so more than 1 client can be with the server in the same chat.
This is what I got, but I doubt its going to be very helpful, since it is just 1 permanent stream to and from the server.
private void connect() throws IOException {
showMessage("Trying to connect \n");
connection = new Socket(InetAddress.getByName(serverIP),27499);
showMessage("connected to "+connection.getInetAddress().getHostName());
}
private void streams() throws IOException{
output = new ObjectOutputStream(connection.getOutputStream());
output.flush();
input = new ObjectInputStream(connection.getInputStream());
showMessage("\n streams working");
}
To read from multiple streams in one program, you're going to have to use multithreading. Because reading from streams is synchronous, you'll need to read from one stream for each thread. See the java tutorial on threads for more info on multithreading.
I've done this several times with ServerSocket(int port) and Socket ServerSocket.accept(). This can be pretty simple by having it listen to the one port you want your chat server client listening on. The main thread will block waiting for the next client to connect, then return the Socket object to that specific client. Usually you'll want to put them in a list to generically handle n-number of clients.
And, yes, you will probably want to make sure each Socket is in a different thread, but that's entirely up to you as the programmer.
Remember, there is no need to re-direct to another port on the server, by virtue of the client using a different source port, the unique 5-tuple (SrcIP, SrcPort, DstIP, DstPort, TCP/UDP/other IP protocol) will allow the one server port to be re-used. Hence why we all use stackoverflow.com port 80.
Happy Coding.
Made something like that a few months back. basically I used a separate ServerSocket and Thread per client server side. When client connects you register that port's input and output streams to a fixed pool and block until input is sent. then you copy the input to each of the other clients and send. here is a basic program run from command line:
Server code:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class ChatServer {
static int PORT_NUMBER = 2012;
public static void main(String[] args) throws IOException {
while (true) {
try (ServerSocket ss = new ServerSocket(PORT_NUMBER)) {
System.out.println("Server waiting #" + ss.getInetAddress());
Socket s = ss.accept();
System.out.println("connection from:" + s.getInetAddress());
new Worker(s).start();
}
}
}
static class Worker extends Thread {
final static ArrayList<PrintStream> os = new ArrayList(10);
Socket clientSocket;
BufferedReader fromClient;
public Worker(Socket clientSocket) throws IOException {
this.clientSocket = clientSocket;
PrintStream toClient=new PrintStream(new BufferedOutputStream(this.clientSocket.getOutputStream()));
toClient.println("connected to server");
os.add(toClient);
fromClient = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream()));
}
#Override
public void run() {
while (true) {
try {
String message = fromClient.readLine();
synchronized (os) {
for (PrintStream toClient : os) {
toClient.println(message);
toClient.flush();
}
}
} catch (IOException ex) {
//user discnnected
try {
clientSocket.close();
} catch (IOException ex1) {
}
}
}
}
}
}
Client code:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
public class Client {
public static void main(String[] args) throws IOException {
final BufferedReader fromUser = new BufferedReader(new InputStreamReader(System.in));
PrintStream toUser = System.out;
BufferedReader fromServer;
final PrintStream toServer;
Socket s = null;
System.out.println("Server IP Address?");
String host;
String port = "";
host = fromUser.readLine();
System.out.println("Server Port Number?");
port = fromUser.readLine();
s = new Socket(host, Integer.valueOf(port));
int read;
char[] buffer = new char[1024];
fromServer = new BufferedReader(new InputStreamReader(s.getInputStream()));
toServer = new PrintStream(s.getOutputStream());
new Thread() {
#Override
public void run() {
while (true) {
try {
toServer.println(">>>" + fromUser.readLine());
toServer.flush();
} catch (IOException ex) {
System.err.println(ex);
}
}
}
}.start();
while (true) {
while ((read = fromServer.read(buffer)) != -1) {
toUser.print(String.valueOf(buffer, 0, read));
}
toUser.flush();
}
}
}