I am creating a java server and a java client.
I need to send from server to client and viceversa an object and then an array of objects.
How can I achieve this? Do I need to serialize the objects classes?
This is the server:
import java.io.*;
import java.net.*;
public class Server extends Thread {
private final ServerSocket Server;
public static void main(String[] args) throws Exception {
new Server();
}
public Server() throws Exception {
Server = new ServerSocket(3000);
System.out.println("Server started on port 3000.");
this.start();
}
#Override
public void run() {
while (true) {
try {
System.out.println("Server is listening to new connections...");
Socket client = Server.accept();
System.out.println("Connection accepted from: " + client.getInetAddress());
Connect c = new Connect(client);
} catch (IOException exception) {
System.out.println(exception.getMessage());
}
}
}
class Connect extends Thread {
private Socket client = null;
BufferedReader in = null;
PrintStream out = null;
public Connect(Socket clientSocket) {
client = clientSocket;
try {
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
out = new PrintStream(client.getOutputStream(), true);
} catch (IOException mainException) {
try {
client.close();
} catch (IOException exception) {
System.out.println(exception.getMessage());
}
}
this.start();
}
#Override
public void run() {
try {
out.close();
in.close();
client.close();
} catch (IOException exception) {
System.out.println(exception.getMessage());
}
}
}
This is my client:
import java.io.*;
import java.net.*;
public class Client {
String remoteAddress = "localhost";
BufferedReader in = null;
PrintStream out = null;
Socket socket = null;
String message = null;
String username = null;
String password = null;
public Client(String username, String password) {
this.username = username;
this.password = password;
}
public String connect() {
try {
// begin a new client connection
socket = new Socket(remoteAddress, 3000);
// open I-O channels
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintStream(socket.getOutputStream(), true);
} catch (Exception exception) {
return false;
System.out.println(exception.getMessage());
}
return "ERROR";
}
public boolean disconnect() throws IOException {
// close flushes I-O with the server
out.close();
in.close();
return true;
}
}
This, instead, is one class:
class Contact {
private String name;
private String surname;
private String telephone;
private String birthday;
public String getName() {
return name;
}
public String getSurname() {
return surname;
}
public String getTelephone() {
return telephone;
}
public String getBirthday() {
return birthday;
}
public void setName(String value) {
name = value;
}
public void setSurname(String value) {
surname = value;
}
public void setTelephone(String value) {
telephone = value;
}
public void setBirthday(String value) {
birthday = value;
}
}
Currently just the server can send data (objects array or only object) to client but I'm thinking about make both able to do.
Also, it'd be nice about to send an object (like the class above), an array of same object and an array of different objects (I can't obtain it with classic arrays, right? May I use ArrayList?)
Thank you.
what about java.io.ObjectOutputStream ? try this http://docs.oracle.com/javase/7/docs/api/java/io/ObjectOutputStream.html
EDIT: here's the example included in the javadoc of the class -slightly modified-, as suggested in the comments:
ObjectOutputStream oos = new ObjectOutputStream(client.getOutputStream());
oos.writeInt(12345);
oos.writeObject("Today");
oos.writeObject(new Date());
oos.close();
and there should be a java.io.ObjectInputStream on the opposite side.
Yes You shoud use serialization for that.
In that case You could use ObjectOutpuStream and writeObject() method. So it is very simple to manage this without thinking about counting bits etc.
http://www.tutorialspoint.com/java/java_serialization.htm
Related
I have 2 sockets: a client socket (Client class) and a concurrent server socket (ServerC Class) that can handle more clients at same time.
The thread server sends an array to the client when it connects.
If I update the array inside the thread server, then the program works correctly and the next client receives the updated array when it connects.
The trouble starts when the client updates the received array but if a new client connects to the server then the array is not the "new" one. That means that the objects aren't shared.
Is it normal? Is it possible to fix that?
Thank you and sorry for my english.
public class Person implements Serializable {
private String name;
private int age;
public Person(String name, int age){
this.name=name;
this.age=age;
}
public void setNome (String name){
this.name = name;
}
#Override
public String toString(){
return name + " " + age;
}
}
public class Client {
public static void main(String[] args) {
try {
Socket socketClient = new Socket("127.0.0.1",1500);
ObjectOutputStream outToServer = new ObjectOutputStream(socketClient.getOutputStream());
ObjectInputStream inFromServer = new ObjectInputStream(socketClient.getInputStream());
ArrayList<Person> people = (ArrayList<Person>)inFromServer.readObject();
for (Person p : people) {
System.out.println(p); //The second client will print Kevin too
}
people.add(new Person("John",54)); //This person won't be never printed for new clients
socketClient.close();
outToServer.close();
inFromServer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class ServerC {
public static void main(String[] args) {
ArrayList<Person> people = new ArrayList<Person>();
people.add(new Person("Alex",21));
ServerSocket socketServer = null;
try {
socketServer = new ServerSocket(1500);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
int id=0;
while (true) {
try {
Socket socket = socketServer.accept();
id = id + 1;
ClientServiceThread cst = new ClientServiceThread(socket,id, people);
cst.start();
} catch (IOException e) {
break;
}
}
}
}
class ClientServiceThread extends Thread {
private Socket socket;
private int id=-1;
private ArrayList<Person> people;
public ClientServiceThread (Socket socket, int id, ArrayList<Person> people) {
this.socket = socket;
this.id=id;
this.people = people;
}
public void run() {
System.out.println(people);
try {
ObjectOutputStream outToClient = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream inFromClient = new ObjectInputStream(socket.getInputStream());
outToClient.writeObject(people);
people.add(new Person("Kevin",7));
outToClient.close();
inFromClient.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
I have been trying to make a multiple client chatting apps for a few days, and I have read the document below, and find some suggestions online, and I come up with the below code.
https://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html#later
What I am thinking is to make an app and start the Server, and Send the Message by the methods
"startServer();" and
"sendFromServer(Serializable data)";
~~~~~The Problem is I start startServer() method the app turn frozen, so I know I am doing it the wrong way.~~~~~~~~
Can anyone please give me some hint on how to correctly create a multiple client-server app?
public class Server {
private ServerSocket server;
private Socket socket;
private int port;
private Consumer<Serializable> consume;
private ConnectionThread thread;
private List<ConnectionThread> threads =
new ArrayList<ConnectionThread>();
public Server(int port, Consumer<Serializable> consume){
this.port= port;
this.consume = consume;
try {
server = new ServerSocket(port);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void startServer() {
if(server == null) {
System.out.println("no server");
}
while(true) {
try {
socket = server.accept();
} catch (IOException e) {
e.printStackTrace();
}
ConnectionThread thread =new ConnectionThread(socket);
threads.add(thread);
thread.start();
}
}
public void sendFromServer(Serializable data) throws IOException {
thread.out.writeObject(data);
}
private class ConnectionThread extends Thread {
private Socket socket;
private ObjectOutputStream out;
private ConnectionThread(Socket socket){
this.socket = socket;
}
#Override
public void run(){
try {
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
this.out = out;
while(true){
Serializable data = (Serializable)in.readObject();
consume.accept(data);
}
}catch (IOException e){
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
Client Side: (I am trying to make one Pane holding the two chats at the moment, using two buttons to call the"startServer();" and "startClient();" respectively)
public class Client {
private int port;
private String ip;
private Consumer<Serializable> consume;
private ConnectionThread thread = new ConnectionThread();
public Client(int port, String ip, Consumer<Serializable> consume){
this.port = port;
this.ip = ip;
this.consume = consume;
}
public void startClient(){
thread.start();
}
public void sendFromClient(Serializable data) throws IOException{
thread.out.writeObject(data);
}
private class ConnectionThread extends Thread{
private Socket socket;
private ObjectOutputStream out;
#Override
public void run(){
try(
Socket socket = new Socket(ip, port);
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
) {
this.out = out;
while(true){
Serializable data = (Serializable)in.readObject();
consume.accept(data);
}
} catch (Exception e) {
e.printStackTrace();;
}
}
}
}
the FXML controller class
public class chatController{
#FXML private TextArea SerBoard, CliBoard;
#FXML private TextField SerTxt,CliTxt;
#FXML private Button SerConnect, CliConnect;
private Server server = createSer();
private Client client = createCli();
private int port= 5555;
private String ip = "localhost";
private boolean connected =
(server==null && client==null)? false: true;
#FXML
public void setOnSerConnect(ActionEvent event) {
server.startServer();
}
#FXML
public void setOnCliConnect(ActionEvent event) {
client.startClient();
}
private Client createCli() {
Client client = new Client(port, ip, data->{
Platform.runLater(() -> {
CliBoard.appendText(data.toString());
});
});
System.out.println("Client connect");
return client;
}
private Server createSer() {
Server server = new Server(port, data->{
Platform.runLater(()->{
SerBoard.appendText(data.toString());
});
});
System.out.println("Server connect");
return server;
}
#FXML
public void setOnSerText(ActionEvent event) {
if(connected) {
String input = SerTxt.getText();
String mes = "Server: "+ input + "\n";
SerTxt.clear();
SerBoard.appendText(mes);
try {
server.sendFromServer(mes);
} catch (IOException e) {
e.printStackTrace();
}
}
}
#FXML
public void setOnCliText(ActionEvent event) {
if(connected) {
String input = SerTxt.getText();
String mes = "Client: "+ input + "\n";
SerTxt.clear();
SerBoard.appendText(mes);
try {
client.sendFromClient(mes);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Should be rather
public void startServer() {
if(server == null) {
System.out.println("no server");
}
while(true) {
try {
socket = server.accept();
ConnectionThread thread =new ConnectionThread(socket);
threads.add(thread);
thread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
This way u will acceppt all client connections.
Also startServer must be invoked using Platform.runLater as well.
I'm trying to get an object from the server, but it does not work.
Relevant section from the server (By Debug I see that he is really sending the correct object):
public static void main(String[] args){
launch(args);
}
public void start(Stage primaryStage) {
BorderPane mainPane = new BorderPane();
mainPane.setStyle("-fx-border-color: black;");
mainPane.setPadding(new Insets(5,5,5,5));
GridPane gridPane = new GridPane();
gridPane.setPadding(new Insets(5,5,5,5));
gridPane.add(lblStatus,0,1);
gridPane.add(lblDate,0,2);
mainPane.setTop(gridPane);
createTableView();
mainPane.setCenter(tableView);
Scene scene = new Scene(mainPane, 700, 250);
primaryStage.setTitle("Server"); // Set the window title
primaryStage.setScene(scene); // Place the scene in the window
primaryStage.show(); // Display the window
primaryStage.setAlwaysOnTop(true);
primaryStage.setOnCloseRequest(
new EventHandler<WindowEvent>(){
public void handle(WindowEvent event) {
try {
Platform.exit();
System.exit(0);
serverSocket.close();
socket.close();
}
catch(SocketException ex){
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
catch (IOException e) {
// TODO Auto-generated catch block
Platform.exit();
System.exit(0);
}
}
});
connectToDB();
connectionDate=new Date();
Platform.runLater(() ->lblDate.setText(("Server started at \t"+connectionDate)));
Platform.runLater(() ->lblStatus.setText(connectionStatus));
new Thread( () ->
{
try{
// Create a server socket
serverSocket = new ServerSocket(8000);
while (true){
// Listen for a connection request
socket = serverSocket.accept();
this.clientNo++;
clientRequest clientDetails = new clientRequest(clientNo, new Date(), "New Clinet");
addRowToServerTable(clientDetails);
new Thread(new HandleAClient(socket)).start();
}
}
catch(SocketException ex){
}
catch(IOException ex){
}
}).start();
}
/** Connect to DB */
private void connectToDB(){
// Connection to the database
try{
Class.forName(driver); // Load the JDBC driver
System.out.println("Driver Loaded");
connection = DriverManager.getConnection(url, username, password); // Establish a connection
System.out.println("Connected to " + url);
connectionStatus = "Connected to \t" + url;
}
catch (java.lang.Exception ex){
ex.printStackTrace();
connectionStatus = ex.toString();
}
}
// Define the thread class for handling new connection
class HandleAClient implements Runnable{
private Socket socket; // A connected socket
/** Construct a thread */
public HandleAClient(Socket socket){
this.socket = socket;
}
/** Run a thread */
public void run(){
try{
// Create data input and output streams
ObjectOutputStream outputToClient = new ObjectOutputStream(
socket.getOutputStream());
DataInputStream inputFromClient = new DataInputStream(
socket.getInputStream());
// Continuously serve the client
while (true){
// Receive sql from the client
String sql = inputFromClient.readUTF();
clientRequest clientDetails = new clientRequest(clientNo, new Date(),"New Query");
addRowToServerTable(clientDetails);
// Execute SQL
Object[] rows = executeSQL(sql);
outputToClient.writeObject(rows);
}
}
catch(SocketException ex){
try{
serverSocket.close();
//socket.close();
}
catch (IOException e){
}
}
catch(IOException ex){
}
}
Relevant section from the client (Probably the mistake on the client, when it receives the object he jumps line ".start ();" Of the Thread.):
private void connectToServer(){
try{
// Create a socket to connect to the server
socket = new Socket(host, 8000);
// Create an input stream to receive Object from the server
fromServer = new ObjectInputStream(socket.getInputStream());
// Create an output stream to send data to the server
toServer = new DataOutputStream(socket.getOutputStream());
}
catch (Exception ex){
ex.printStackTrace();
}
}
private void sendAndGetFromServer(String sqlQuery){
new Thread(() ->{
try{
System.out.println("a1");
// Send sql query to server
toServer.writeUTF(sqlQuery);
//toServer.flush();
// Get notification from the server
Student[] rows = (Student[])fromServer.readObject();
setRowsInTable(rows);
}
catch(SocketException ex){
try{
socket.close();
}
catch (IOException e){
}
}
catch (Exception ex){
}
}).start();
I tried to separate into two Thread (One Input and other Output in Server and client) according to the answers I read here --- but it didn't help.
Also tried to change the order of Input and Output --- without success.
No errors!
The client don't get the object.
What's the problem here?
Edit. Student class:
public class Student implements Externalizable
{
private final SimpleIntegerProperty ID;
private final SimpleStringProperty firstName;
private final SimpleStringProperty lastName;
private final SimpleStringProperty address;
private final SimpleObjectProperty<Date> birthDate;
private final SimpleStringProperty department;
private final SimpleIntegerProperty pointsAmount;
private final SimpleObjectProperty<Date> startStudyingDate;
private final SimpleIntegerProperty failedAmount;
private final SimpleDoubleProperty average;
private final SimpleIntegerProperty lavelByGrade;
private final SimpleStringProperty pic;
public Student(int ID, String firstName, String lastName, String address,
Date birthDate, String department,
int pointsAmount, Date startStudyingDate, int failedAmount,
double average, int lavelByGrade, String pic){
this.ID= new SimpleIntegerProperty(ID);
this.firstName= new SimpleStringProperty(firstName);
this.lastName= new SimpleStringProperty(lastName);
this.address= new SimpleStringProperty(address);
this.birthDate= new SimpleObjectProperty<Date>(birthDate);
this.department= new SimpleStringProperty(department);
this.pointsAmount= new SimpleIntegerProperty(pointsAmount);
this.startStudyingDate= new SimpleObjectProperty<Date>(startStudyingDate);
this.failedAmount= new SimpleIntegerProperty(failedAmount);
this.average= new SimpleDoubleProperty(average);
this.lavelByGrade= new SimpleIntegerProperty(lavelByGrade);
this.pic = new SimpleStringProperty(pic);
}
public int getID() {
return ID.get();
}
public void setID(int ID) {
this.ID.set(ID);
}
public String getFirstName() {
return firstName.get();
}
public void setFirstName(String firstName) {
this.firstName.set(firstName);
}
public String getLastName() {
return lastName.get();
}
public void setLastName(String lastName) {
this.lastName.set(lastName);
}
public String getAddress() {
return address.get();
}
public void setAddress(String address) {
this.address.set(address);
}
public Date getBirthDate() {
return birthDate.get();
}
public void setBirthDate(Date birthDate) {
this.birthDate.set(birthDate);
}
public String getDepartment() {
return department.get();
}
public void setDepartment(String department) {
this.department.set(department);
}
public int getPointsAmount() {
return pointsAmount.get();
}
public void setPointsAmount(int pointsAmount) {
this.pointsAmount.set(pointsAmount);
}
public Date getStartStudyingDate() {
return startStudyingDate.get();
}
public void setStartStudyingDate(Date startStudyingDate) {
this.startStudyingDate.set(startStudyingDate);
}
public int getFailedAmount() {
return failedAmount.get();
}
public void setFailedAmount(int failedAmount) {
this.failedAmount.set(failedAmount);
}
public double getAverage() {
return average.get();
}
public void setAverage(Double average) {
this.average.set(average);
}
public int getLavelByGrade() {
return lavelByGrade.get();
}
public void setLavelByGrade(int lavelByGrade) {
this.lavelByGrade.set(lavelByGrade);
}
public String getPic() {
return pic.get();
}
public void setPic(String pic) {
this.pic.set(pic);
}
#Override
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
setID(in.readInt());
setFirstName((String)in.readObject());
setLastName((String)in.readObject());
setAddress((String)in.readObject());
setBirthDate((Date)in.readObject());
setDepartment((String)in.readObject());
setPointsAmount(in.readInt());
setStartStudyingDate((Date)in.readObject());
setFailedAmount(in.readInt());
setAverage(in.readDouble());
setLavelByGrade(in.readInt());
setPic((String)in.readObject());
}
#Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeInt(getID());
out.writeObject(getFirstName());
out.writeObject(getLastName());
out.writeObject(getAddress());
out.writeObject(getBirthDate());
out.writeObject(getDepartment());
out.writeInt(getPointsAmount());
out.writeObject(getStartStudyingDate());
out.writeInt(getFailedAmount());
out.writeDouble(getAverage());
out.writeInt(getLavelByGrade());
out.writeObject(getPic());
}
}
JavaFX properties are not Serializable. So if you try to serialize an object that uses JavaFX properties for its state, you will get an exception.
You have a couple of options here. One is simply to not use Java object serialization, but some other serialization technique, such as representing the object with JSON.
The other option is to implement Externalizable instead of Serializable. Externalizable is a subinterface of Serializable in which you define your own process for serializing and deserializing the data. In particular, instead of serializing the JavaFX properties themselves, just serialize their contents.
A simple example:
import java.io.Externalizable ;
import java.io.IOException ;
import java.io.ObjectInput ;
import java.io.ObjectOutput ;
import javafx.beans.property.IntegerProperty ;
import javafx.beans.property.SimpleIntegerProperty ;
import javafx.beans.property.SimpleStringProperty ;
import javafx.beans.property.StringProperty ;
public class Person implements Externalizable {
private final StringProperty name = new SimpleStringProperty();
private final IntegerProperty id = new SimpleIntegerProperty();
public StringProperty nameProperty() {
return name ;
}
public final String getName() {
return nameProperty().get();
}
public final void setName(String name) {
nameProperty().set(name);
}
public IntegerProperty idProperty() {
return id ;
}
public final int getId() {
return idProperty().get();
}
public final void setId(int id) {
idProperty().set(id);
}
// important: must have a no-arg constructor:
public Person() { }
public Person(int id, String name) {
setId(id);
setName(name);
}
#Override
public void writeExternal(ObjectOutput out) throws IOException {
// write id then name
// note we write the contents of the properties, not the properties
// themselves, as the properties are not serializable:
out.writeInt(getId());
out.writeObject(getName());
}
#Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
// read data back in same order:
setId(in.readInt());
setName((String)in.readObject());
}
}
Note that this class has a pretty simple structure, so it's easy to implement these two methods. For more complex objects - particularly those which may potentially have circular references - you need to work a bit harder.
Since the class defined above implements Externalizable, it also implements Serializable, and can be serialized in the usual way:
ObjectOutputStream oos = ... ;
oos.writeObject(new Person(007, "James Bond"));
Read my blog post on JavaFX beans and JPA for more.
Try with this post, search part with following text and Externalizable: For quite a long time, I thought the lack of support for Serialization from JavaFX properties really prevented them from being used in any server-side capacity.
http://www.marshall.edu/genomicjava/2014/05/09/one-bean-to-bind-them-all/
https://gist.github.com/james-d/e485ac525c71e20bb453
This is the simple client/server socket app for my faculty project. First, the Server class should be run, and then if Client class runs - it prints out the IP address of the local machine and the port that's been used.
I can't figure out one thing:
How and WHERE to create a method in class that will close(stop) the Server? And
how to make this like an event or something, for example if client
sends "stop" it should somehow stop the server...
SERVER.JAVA
import java.io.*;
import java.net.*;
public class Server {
public static void main(String[] args) {
System.out.println("The server has been summoned.\n");
System.out.println("The server is waiting for client to come...");
try {
ServerSocket servertest = new ServerSocket(2014);
while (true) {
try {
Socket ser = servertest.accept();
new ThreadSer(ser).start();
} catch (IOException e) {}
}
} catch (IOException e) {System.err.println(e);}
}
public static class ThreadSer extends Thread {
private Socket s;
public ThreadSer(Socket s) {
this.s = s;
}
#Override
public void run() {
try {
String response = "This is the IP: " + s.getLocalAddress() + " that has come via port: "
+ s.getLocalPort() + "\r\n";
OutputStream out = s.getOutputStream();
out.write(response.getBytes());
} catch (IOException e) { System.err.println(e); }
}}}
CLIENT.JAVA
import java.io.*;
import java.net.*;
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException {
Socket socket = new Socket("localhost", 2014);
new OutputThread(socket.getInputStream()).start();
}
public static class OutputThread extends Thread {
private InputStream inputstream;
public OutputThread(InputStream inputstream) {
this.inputstream = inputstream;
}
#Override
public void run() {
BufferedReader input = new BufferedReader(new InputStreamReader(inputstream));
while (true) {
try {
String line = input.readLine();
System.out.println(line);
} catch (IOException exception) {
exception.printStackTrace();
break;
}
}
}}}
You should constantly ask for the inputstream of the client.. put it in the loop that always accept for the client input..
example:
public static class ThreadSer extends Thread {
private Socket s;
public ThreadSer(Socket s) {
this.s = s;
}
#Override
public void run() {
try {
String response = "This is the IP: " + s.getLocalAddress() + " that has come via port: "
+ s.getLocalPort() + "\r\n";
ObjectInputStream input = new ObjectInputStream(s.getInputStream());
while(true)
{
Object object = input.readObject();
if(object instanceof String)
{
String command = ((String) object).trim();
if(command.equals("stop"))
break;
}
}
s.close();
} catch (IOException e) { System.err.println(e); }
}}}
I am currently developing chat application working over Internet.currently my application working fine over LAN but not working over Internet.I have also used port forwarding.I have done setting in modem and forward the port to private IP address but still it's not working.I got the error that "server isn't found".Please suggest me what I have to do and tell,Am I done the correct setting in modem or not??
Below is my server code...
Server.java
import java.util.*;
import java.net.*;
import java.io.*;
class Server implements ChatConstants
{
private static Vector list;
private ServerSocket ssocket ;
private Service service;
private static Socket socket;
private boolean done=false;
private static Hashtable userTable = new Hashtable();
private static Hashtable _userList = new Hashtable();
private static Hashtable _conflist = new Hashtable();
public Server() throws UnknownHostException
{
System.out.println("Initializing...");
list=new Vector(BACKLOG);
try {
ssocket= new ServerSocket(SERVER_PORT,BACKLOG);
}
catch(Exception e) {
e.printStackTrace();
System.out.println("Inside constructor"+e);
}
start();
}
public void start() throws UnknownHostException
{
byte[] data;
int header;
Socket _socket = null;
String hostname = null;
System.out.println("Server successfully started at "
+InetAddress.getLocalHost().toString()
+" port "+SERVER_PORT);
while(!done) {
try
{
_socket=ssocket.accept();
if(_socket != null) {
synchronized(list) {
list.addElement(_socket);
}
DataInputStream dis=new DataInputStream(_socket.getInputStream());
data = new byte[MAX_MESSAGE_SIZE];
dis.read(data);
Message message = ((Message)ChatUtils.bytesToObject(data));
System.out.println("Joined client "
+message._username+" at "+message._host+"...");
synchronized(userTable) {
userTable.put(message._username,_socket);
}
addUser(message);
sendUserList(message);
writeToClients(message);
service = new Service(_socket,hostname,message._user);
}
}
catch(Exception e) {
e.printStackTrace();
System.out.println("Thread exception"+e);
try {
_socket.close();
}
catch(Exception ex) {
ex.printStackTrace();
System.out.println("ERROR CLOSING SOCKET");
}
}
}//END WHILE
}
private void addUser(Message message)
{
synchronized(_userList) {
_userList.put(message._user.toString(),message._user);
}
}
public static void updateUser(User user)
{
User myuser;
synchronized(_userList) {
_userList.put(user.toString(),user);
}
}
public static synchronized void writeToClients(Message message)
{
byte[] data;
DataOutputStream dos;
for(int count=0;count<list.size();count++) {
try {
dos=new
DataOutputStream(((Socket)list.elementAt(count)).getOutputStream());
data=ChatUtils.objectToBytes(message);
dos.write(data,0,data.length);
}
catch(Exception e) {
e.printStackTrace();
System.out.println("Output exception");
}
}//END FOR
}
public static void writeToClient(Message message)
{
Socket socket;
byte[] data;
DataOutputStream dos;
synchronized(userTable) {
try {
socket = (Socket)userTable.get(message._destination);
dos=new DataOutputStream(socket.getOutputStream());
data=ChatUtils.objectToBytes(message);
dos.write(data,0,data.length);
}
catch(Exception e) {
e.printStackTrace();
System.out.println("SEND EXCEPTION"+e);
}
}
}
public static void sendConferenceListToClient(Message message)
{
Socket socket;
byte[] data;
DataOutputStream dos;
synchronized(userTable) {
try {
Message mymessage= new Message(CONFERENCE_LIST);
Vector vector = (Vector)
_conflist.get(message._destination);
mymessage._username = message._username;
mymessage._destination = message._destination;
mymessage.userlist = vector;
socket = (Socket)userTable.get(message._username);
if(socket!=null) {
dos=new DataOutputStream(socket.getOutputStream());
data=ChatUtils.objectToBytes(mymessage);
dos.write(data,0,data.length);
}
}
catch(Exception e) {
e.printStackTrace();
System.out.println("CONFERENCE LIST EXCEPTION"+e);
}
}
}
public static void writeToPublicChat(Message message)
{
Socket socket;
byte[] data;
DataOutputStream dos;
synchronized(_conflist) {
try {
Vector svector = (Vector)_conflist.get(message._destination);
for(int cnt=0;cnt<svector.size();cnt++) {
synchronized(userTable) {
try {
socket = (Socket)userTable.get((svector.get(cnt).toString()));
if(socket!=null) {
dos=new DataOutputStream(socket.getOutputStream());
data=ChatUtils.objectToBytes(message);
dos.write(data,0,data.length);
}
}
catch(Exception e) {
e.printStackTrace();
System.out.println("PUBLIC CHAT EXCEPTION"+e);
}
}
}
} catch(Exception e){
e.printStackTrace();
System.out.println("PUBLIC EXCEPTION"+e);
}
}
}
public static void inviteToPublicChat(Vector svector,Message message)
{
Socket socket;
byte[] data;
DataOutputStream dos;
synchronized(_conflist) {
for(int cnt=0;cnt<svector.size();cnt++) {
synchronized(userTable) {
try {
socket = (Socket)userTable.get((svector.get(cnt).toString()));
if(socket != null) {
dos=new DataOutputStream(socket.getOutputStream());
data=ChatUtils.objectToBytes(message);
dos.write(data,0,data.length);
}
}
catch(Exception e) {
e.printStackTrace();
System.out.println("PUBLIC INVITE EXCEPTION"+e);
}
}
}
}
}
private void sendUserList(Message message)
{
int header=0;
String destination;
header=message._header;
destination = message._destination;
message._header = USERS_LIST;
message._destination = message._username;
message.userlist = new Vector(_userList.values());
writeToClient(message);
//Restore the headers
message._destination = destination;
message._header = header;
}
public static synchronized void removeUser(User user)
{
try {
Socket socket = (Socket)userTable.get(user.toString());
list.removeElement(socket);
_userList.remove(user.toString());
userTable.remove(user.toString());
}
catch(Exception e) {
e.printStackTrace();
System.out.println("ERROR REMOVING SOCKET "+e);
}
}
public static synchronized void processClientMessage(Message message)
{
switch(message._header) {
case CHANGE_STATUS:
updateUser(message._user);
writeToClients(message);
break;
case CLIENT_LOGOUT:
removeUser(message._user);
writeToClients(message);
break;
case CONFERENCE_CREATE:
Vector myvector = new Vector();
myvector.add(message._username);
_conflist.put(message._user.toString(),myvector);
case CONFERENCE_INVITE:
inviteToPublicChat(message.userlist,message);
break;
case CONFERENCE_JOIN:
Vector vector=null;
vector = (Vector)
_conflist.get(message._destination.toString());
vector.add(message._username);
_conflist.put(message._destination.toString(),vector);
writeToPublicChat(message);
break;
case CONFERENCE_DENY:
//_conflist.remove(message._user.toString(),message.userlist);
writeToPublicChat(message);
break;
case CONFERENCE_LEAVE:
Vector vectors =(Vector)
_conflist.get(message._destination.toString());
for(int count=0;count<vectors.size();count++) {
if(message._username.equals((vectors.elementAt(count).toString())))
vectors.remove(count);
}
if(vectors.size() != 0)
_conflist.put(message._user.toString(),vectors);
else//IF THERE ARE NO MORE USERS
_conflist.remove(message._user.toString());//DONE CONFERENCE
writeToPublicChat(message);
break;
case PUBLIC_CHAT:
writeToPublicChat(message);
break;
case CONFERENCE_LIST:
sendConferenceListToClient(message);
break;
default:
writeToClient(message);
}
}
public static void main(String args[]) throws Exception
{
Server chatserver=new Server();
}
}
//
// Service: Service class for each clients connected to server.
//
class Service implements Runnable, ChatConstants
{
private DataInputStream dis;
private Socket socket;
private boolean done=false;
private Thread thread;
private String hostname;
private User user;
public Service(Socket _socket,String _hostname,User user)
{
try {
this.socket = _socket;
this.hostname=_hostname;
this.user = user;
dis=new DataInputStream(socket.getInputStream());
thread=new Thread(this,"SERVICE");
thread.start();
}
catch(Exception e){
e.printStackTrace();
System.out.println("service constructor"+e);
}
}
public void run()
{
byte[] data;
while(!done)
{
try {
data = new byte[MAX_MESSAGE_SIZE];
dis.read(data);
Message message = ((Message)ChatUtils.bytesToObject(data));
Server.processClientMessage(message);
}
catch(Exception e) {
e.printStackTrace();
done = true;
Server.removeUser(user);
Message message = new Message(CLIENT_LOGOUT);
user.isOnline = OFFLINE;
message._user = user;
Server.writeToClients(message);
try {
socket.close();
} catch(Exception se) {
se.printStackTrace();
System.out.println("ERROR CLOSING SOCKET "+se);
}
//System.out.println("SERVICE THREAD EXCEPTION"+e);
}
}//END WHILE
}
}
Thanks in advance.
I think the
ssocket= new ServerSocket(SERVER_PORT,BACKLOG);
is making the issue. Use the version
ssocket= new ServerSocket(SERVER_PORT,BACKLOG,LOCAL_INET_ADDRESS);
and bind server to some constant local IP. Now use the port forwarding in the modem, to forward all requests to that local ip. Make sure that the firewall is not preventing you to use the port. Since firewall may allow a local networking but not to web.