I'm new to socket programming in Java and I'm trying to create a simple chat between 2 clients through a server. The server will receive message from this client and send to the other.
Server
public class ServerV2 extends JFrame {
/**
*
*/
private static final long serialVersionUID = -1958631621285336523L;
private ServerSocket serverSocket;
private ObjectOutputStream outputStream;
private int port;
private ArrayList<ClientHandler> clients = new ArrayList<ClientHandler>();
private JTextArea messageBox;
private void initializeUI() {
messageBox = new JTextArea();
add(new JScrollPane(messageBox), BorderLayout.CENTER);
setTitle("Server");
setSize(256, 256);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public ServerV2(int port) {
this.port = port;
initializeUI();
}
public void startServer() {
try {
serverSocket = new ServerSocket(port, 100);
while (true) {
try {
Socket clientSocket = serverSocket.accept();
ClientHandler client = new ClientHandler(this, clientSocket);
clients.add(client);
client.start();
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
void sendMessage(String message, ClientHandler fromClient) {
try {
for (ClientHandler clientHandler : clients) {
if (!clientHandler.equals(fromClient)) {
outputStream = new ObjectOutputStream(
clientHandler.getClient().getOutputStream());
outputStream.writeObject(message);
outputStream.flush();
}
}
showMessage(message, fromClient);
} catch (IOException e) {
System.out.println("What the heck are you trying to send?");
}
}
void showMessage(String message, ClientHandler fromClient) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
messageBox.append("\n" + fromClient.getUserName() + " said "
+ message);
}
});
}}
ClientHandler
public class ClientHandler extends Thread {
private ServerV2 server;
private Socket clientSocket;
private String userName;
private ObjectInputStream inputStream;
private String message;
public String getUserName() {
return userName;
}
public Socket getClient() {
return clientSocket;
}
public ClientHandler(ServerV2 server, Socket client) {
this.server = server;
try {
inputStream = new ObjectInputStream(client.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
this.clientSocket = client;
}
#Override
public void run() {
try {
userName = (String)inputStream.readObject();
readMessage();
} catch (Exception e) {
e.printStackTrace();
}
}
private void readMessage() throws IOException {
do {
try {
message = (String)inputStream.readObject();
server.sendMessage(message, this);
} catch (ClassNotFoundException e) {
}
} while (!message.equals("EXIT"));
}
#Override
public boolean equals(Object obj) {
if (obj == null) return false;
ClientHandler client = (ClientHandler)obj;
if (this.userName.equals(client.getUserName())) return true;
return false;
}}
Client
public class Client extends JFrame {
/**
*
*/
private static final long serialVersionUID = -3219203310153720970L;
private JTextField txtMessageInput;
private JTextArea messageBox;
private Socket clientSocket;
private String message;
private ObjectOutputStream outputStream;
private ObjectInputStream inputStream;
private String host;
private int port;
private String userName;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Client(String host, int port, String userName) {
this.host = host;
this.port = port;
this.userName = userName;
initializeUI();
}
private void initializeUI() {
txtMessageInput = new JTextField();
txtMessageInput.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
sendMessage(e.getActionCommand());
txtMessageInput.setText("");
}
});
messageBox = new JTextArea();
add(txtMessageInput, BorderLayout.NORTH);
add(new JScrollPane(messageBox), BorderLayout.CENTER);
setTitle("Client");
setSize(256, 256);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public void startClient() {
try {
System.out.println("Starting client with username " + userName);
// Connect to server
connectToServer();
// Setup streams to send and receive data from server
setupStreams();
// send username to server
outputStream.writeObject(userName);
// read messages from server
readMessage();
} catch (EOFException e) {
System.out.println("You closed the connection.");
} catch (IOException e) {
e.printStackTrace();
} finally {
closeConnection();
}
}
private void connectToServer() {
System.out.println("Searching for server ...");
try {
clientSocket = new Socket(InetAddress.getByName(host), port);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Connected to server.");
}
private void setupStreams() throws IOException {
System.out.println("Setup streams ...");
outputStream = new ObjectOutputStream(clientSocket.getOutputStream());
inputStream = new ObjectInputStream(clientSocket.getInputStream());
System.out.println("Streams are setup ...");
}
private void readMessage() throws IOException {
do {
try {
message = (String) inputStream.readObject();
showMessages(message);
} catch (ClassNotFoundException e) {
System.out.println("Blah blah blah, I don't know this language ...");
}
} while (!message.equals("EXIT"));
}
public void sendMessage(String message) {
try {
outputStream.writeObject(message);
outputStream.flush();
showMessages(message);
} catch (IOException e) {
System.out.println("What the heck are you trying to send?");
}
}
private void closeConnection() {
System.out.println("Close connections ...");
try {
inputStream.close();
outputStream.close();
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private void showMessages(String message) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
messageBox.append(message + "\n");
}
});
}}
The problem is when I start 2 clients and a server and send message, the server throws exception
java.io.EOFException
at java.io.ObjectInputStream$BlockDataInputStream.peekByte(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at awesomechat.server.ClientHandler.readMessage(ClientHandler.java:54)
at awesomechat.server.ClientHandler.run(ClientHandler.java:45)
and one client throws
java.io.StreamCorruptedException: invalid type code: AC
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at awesomechat.client.Client.readMessage(Client.java:106)
at awesomechat.client.Client.startClient(Client.java:76)
at awesomechat.client.StartClient.main(StartClient.java:6)
So anyone please show me the point why I get these two exceptions and how to solve it.
Related
I am creating a program where my goal is that on a JButton click in a separate class called ClientChat, I create a server (in my ChatBoxServer class), and within that class, I call my Client program (ChatBoxClient class) to establish the connection. However, my program stalls when I try to call ChatBoxClient.java from ChatBoxServer.java. Is it possible to call my Client class within the Server class, or do I need to separately run the two programs?
ChatBoxServer:
public class ChatBoxServer implements ActionListener {
private ServerSocket ss;
private Socket s;
private ObjectInputStream oin;
private ObjectOutputStream oout;
private ChatBox chat;
private JButton hello;
private String user;
private String user2;
private String host;
public ChatBoxServer(String user, String user2, String host, int port) throws IOException{
setUsers(user, user2);
setHost(host);
chat = new ChatBox();
hello = chat.getSendButton();
hello.addActionListener(this);
createServer(port);
if (!s.isConnected())
JOptionPane.showMessageDialog(null, "Cannot Connect", "Connection Status", JOptionPane.WARNING_MESSAGE);
chat.getChatArea().append("You are now connected!\tType quit to end chat.\n");
readMessage();
}
#Override
public void actionPerformed(ActionEvent e) {
String outgoingMsg = "";
try {
outgoingMsg= chat.getSendField().getText();
chat.getChatArea().append("<" + user +">:\t" + outgoingMsg + "\n");
oout.writeObject(outgoingMsg);
oout.flush();
} catch (IOException e1) {
e1.printStackTrace();
}
if (chat.getSendField().getText().equals("quit")) {
try {
s.close();
oin.close();
} catch (Exception error) {
System.out.println("Server side");
}
}
}
private void createServer(int port) throws IOException {
ss=new ServerSocket(port);
ClientChatTest cct = new ClientChatTest(user, user2, host, port);
s=ss.accept();
oin=new ObjectInputStream(s.getInputStream());
oout=new ObjectOutputStream(s.getOutputStream());
}
private void readMessage() {
String incomingMsg = "";
while (!incomingMsg.equalsIgnoreCase("quit")) {
try {
incomingMsg = (String) oin.readObject();
} catch (ClassNotFoundException | IOException e) {
JOptionPane.showMessageDialog(null, "Server Error", "Connection Status", JOptionPane.WARNING_MESSAGE);
}
chat.getChatArea().append("<" + user2 + ">:\t" + incomingMsg + "\n");
}
}
private void setUsers(String user, String user2) {
this.user = user;
this.user2 = user2;
}
private void setHost(String host) {
this.host = host;
}
}
ChatBoxClient:
public class ChatBoxClient implements ActionListener {
Socket s;
ObjectInputStream oin;
ObjectOutputStream oout;
private ChatBox chat;
JButton hello;
private String user;
private String user2;
public ChatBoxClient(String user, String user2, String hostname, int port) throws IOException {
setUsers(user, user2);
connection(hostname, port);
chat = new ChatBox();
hello = chat.getSendButton();
hello.addActionListener(this);
readMessage();
}
public void connection(String hostname, int port) throws IOException {
s=new Socket(hostname, port);
oout=new ObjectOutputStream(s.getOutputStream());
oin = new ObjectInputStream(s.getInputStream());
if (s.isConnected()) {
chat.getChatArea().append("You are now connected!\tType quit to end chat.\n");
}
}
#Override
public void actionPerformed(ActionEvent e) {
String outgoingMsg="";
try {
outgoingMsg = chat.getSendField().getText();
chat.getChatArea().append("<" + user2 + ">:\t" + outgoingMsg + "\n");
oout.writeObject(outgoingMsg);
oout.flush();
} catch (IOException e1) {
e1.printStackTrace();
}
if (chat.getSendField().getText().equalsIgnoreCase("quit")) {
try {
oin.close();
oout.close();
s.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
private void readMessage() {
String incomingMsg = "";
while (!incomingMsg.equalsIgnoreCase("quit")) {
try {
incomingMsg = (String) oin.readObject();
} catch (ClassNotFoundException | IOException e) {
JOptionPane.showMessageDialog(null, "Server Error", "Connection Status", JOptionPane.WARNING_MESSAGE);
}
chat.getChatArea().append("<" + user + ">:\t" + incomingMsg + "\n");
}
}
private void setUsers(String user, String user2) {
this.user = user;
this.user2 = user2;
}
}
Program works when I separately call the two classes, but not when I call the Client class within my Server class.
I want to create a class that contain two socket I.e socket for client1 and socket for client 2 so that they can chat together.
How can I achieve this.When i run above code i am getting stream corrupted exception .
My chat is not working. Can someone help me out ?
Here is my code .
This is client code for making socket request
Client.java
package customChat;
import java.net.*;
import java.io.*;
import java.util.*;
public class Client
{
private String notif = " *** ";
private ObjectInputStream sInput;
private ObjectOutputStream sOutput;
private Socket socket;
private String server, username;
private int port;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
private RemoteAccess access;
Client(String server, int port,RemoteAccess access ) {
this.server = server;
this.port = port;
this.access = access;
}
public boolean start()
{
try
{
socket = new Socket(server, port);
}
catch(Exception ec) {
display("Error connectiong to server:" + ec);
return false;
}
String msg = "Connection accepted " + socket.getInetAddress() + ":" + socket.getPort();
display(msg);
try
{
sInput= new ObjectInputStream(socket.getInputStream());
sOutput = new ObjectOutputStream(socket.getOutputStream());
}
catch (IOException eIO) {
eIO.printStackTrace();
display("Exception creating new Input/output Streams in client: " + eIO);
return false;
}
new ListenFromServer().start();
try
{
sOutput.writeObject(access);
}
catch (IOException eIO) {
display("Exception doing login : " + eIO);
//disconnect();
return false;
}
return true;
}
private void display(String msg)
{
System.out.println(msg);
}
void sendMessage(RemoteAccess msg)
{
try
{
System.out.println("I am writing for :"+msg.getTo()+": msg "+msg.getMsg());
sOutput.writeObject(msg);
}
catch(IOException e) {
display("Exception writing to server: " + e);
}
}
private void disconnect() {
try {
if(sInput != null) sInput.close();
}
catch(Exception e)
{
e.printStackTrace();
}
try {
if(sOutput != null) sOutput.close();
}
catch(Exception e) {
e.printStackTrace();
}
try{
if(socket != null) socket.close();
}
catch(Exception e) {
e.printStackTrace();
}
}
public static void sendFile()
{
int portNumber = 1502;
String serverAddress = "localhost";
Scanner scan = new Scanner(System.in);
System.out.println("Enter from ");
long from = scan.nextLong();
System.out.println("Enter to");
long to = scan.nextLong();
RemoteAccess access = new RemoteAccess(to,from,"hello");
Client client = new Client(serverAddress, portNumber,access);
if(!client.start())
return;
while(true)
{
System.out.println("Please enter msg:");
System.out.print("> ");
// read message from user
String msg = scan.nextLine();
System.out.println("Sending message");
client.sendMessage(new RemoteAccess(to,from,msg));
}
}
public static void main(String[] args)
{
sendFile();
}
class ListenFromServer extends Thread {
public void run()
{
System.out.println("i am in run method");
while(true)
{
System.out.println("i am in run method 2");
try
{
System.out.println("i am in run method 3");
RemoteAccess access = (RemoteAccess) sInput.readObject();
System.out.println("Message read by:"+access.getFrom());
if(access !=null)
{
System.out.println("Message is :"+access.getFrom());
}
}
catch(IOException e)
{
e.printStackTrace();
System.out.println("Excepion caught while listening from server :"+e);
display(notif + "Server has closed the connection: " + e + notif);
break;
}
catch(ClassNotFoundException e2) {
e2.printStackTrace();
}
}
}
}
}
Server.java
package customChat;
import java.io.*;
import java.net.*;
import java.text.SimpleDateFormat;
import java.util.*;
public class Server {
private SimpleDateFormat sdf;
private int port;
private boolean keepGoing;
private String notif = " *** ";
public static ArrayList<ClientThread> al;
public Server(int port)
{
this.port = port;
sdf = new SimpleDateFormat("HH:mm:ss");
al = new ArrayList<ClientThread>();
}
public void start() {
keepGoing = true;
try
{
ServerSocket serverSocket = new ServerSocket(port);
while(keepGoing)
{
display("Server waiting for Clients on port " + port + ".");
Socket socket = serverSocket.accept();
if(!keepGoing)
break;
ClientThread t = new ClientThread(socket);
Thread t1 =new Thread(t);
System.out.println("Connection initiated by:"+t.access.getFrom());
Server.al.add(t);
t1.start();
}
/*try {
serverSocket.close();
for(int i = 0; i < Server.al.size(); ++i) {
ClientThread tc = Server.al.get(i);
try {
tc.sInput.close();
tc.sOutput.close();
tc.socket.close();
}
catch(IOException ioE) {
ioE.printStackTrace();
}
}
}
catch(Exception e)
{
display("Exception closing the server and clients: " + e);
}*/
}
catch (IOException e) {
String msg = sdf.format(new Date()) + " Exception on new ServerSocket: " + e + "\n";
display(msg);
}
}
/*protected void stop() {
keepGoing = false;
try {
new Socket("localhost", port);
}
catch(Exception e) {
}
}*/
// Display an event to the console
private void display(String msg) {
String time = sdf.format(new Date()) + " " + msg;
System.out.println(time);
}
public static void main(String[] args) {
// start server on port 1500 unless a PortNumber is specified
int portNumber = 1502;
// create a server object and start it
Server server = new Server(portNumber);
server.start();
}
}
ClientThread.java
package customChat;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Date;
/*class ListClient
{
public static ArrayList<ClientThread> al=new ArrayList<>();;
}*/
public class ClientThread implements Runnable {
Socket socket;
ObjectInputStream sInput;
ObjectOutputStream sOutput;
String date;
RemoteAccess access;
public RemoteAccess getAccess() {
return access;
}
public void setAccess(RemoteAccess access) {
this.access = access;
}
// Constructor
ClientThread(Socket socket) {
this.socket = socket;
System.out.println("Thread trying to create Object Input/Output Streams");
try
{
sOutput = new ObjectOutputStream(socket.getOutputStream());
sInput = new ObjectInputStream(socket.getInputStream());
System.out.println("CT input Stream :"+sInput);
access = (RemoteAccess) sInput.readObject();
System.out.println(access.getFrom() +"Joined the chat room");
}
catch (IOException e)
{
e.printStackTrace();
System.out.println("Exception creating new Input/output Streams: " + e);
return;
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
date = new Date().toString() + "\n";
}
/*private void close() {
try {
if(sOutput != null) sOutput.close();
}
catch(Exception e) {
e.printStackTrace();
}
try {
if(sInput != null) sInput.close();
}
catch(Exception e) {
e.printStackTrace();
};
try {
if(socket != null) socket.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
*/
#Override
public void run()
{
System.out.println("List size is :"+Server.al.size());
for(int i=0;i<Server.al.size();i++)
{
try {
System.out.println("Socket input Stream :"+Server.al.get(i).socket.getInputStream());
System.out.println("Socket :"+socket.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
if(Server.al.get(i).access.getFrom()==access.getTo())
{
System.out.println("I am in if part :"+Server.al.get(i).access.getFrom() +"compare to :"+access.getTo());
PairHandler t = null;
try {
t = new PairHandler(access.getTo(),Server.al.get(i).socket,Server.al.get(i).socket.getInputStream(),Server.al.get(i).socket.getOutputStream(),socket.getOutputStream(),socket.getInputStream(),socket);
} catch (IOException e) {
e.printStackTrace();
}
Thread t1 = new Thread(t);
System.out.println("Connection initiated by in CT:"+access.getFrom());
t1.start();
}
else{
System.out.println("I am in else in CT");
}
}
}
}
PairHandler.java
This is where i am using two client socket
package customChat;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
public class PairHandler implements Runnable
{
long stbId;
Socket tvsocket;
ObjectInputStream tvsInput;
ObjectOutputStream tvsOutput;
Socket dtsocket;
ObjectInputStream dtsInput;
ObjectOutputStream dtsOutput;
PairHandler(long stbId,Socket tvsocket,Socket dtsocket)
{
this.stbId = stbId;
this.tvsocket = tvsocket;
this.dtsocket = dtsocket;
try
{
tvsOutput = new ObjectOutputStream(tvsocket.getOutputStream());
dtsOutput = new ObjectOutputStream(dtsocket.getOutputStream());
System.out.println("DT output Stream is :"+dtsOutput);
System.out.println("Tv outPut Stream is :"+tvsOutput);
System.out.println("RH input Stream :"+tvsocket.getInputStream());
tvsInput = new ObjectInputStream(tvsocket.getInputStream());
System.out.println("Tv input Stream is :"+tvsInput);
dtsInput = new ObjectInputStream(dtsocket.getInputStream());
System.out.println("DT input Stream is :"+dtsInput);
}
catch (IOException e)
{
e.printStackTrace();
System.out.println("Exception creating in Pair Handler new Input/output Streams: " + e);
return;
}
}
public PairHandler(long to, Socket socket, InputStream inputStream, OutputStream outputStream,
OutputStream outputStream2, InputStream inputStream2, Socket socket2) {
stbId = to;
tvsocket = socket;
dtsocket = socket2;
try{
tvsOutput = new ObjectOutputStream(outputStream);
dtsOutput = new ObjectOutputStream(outputStream2);
System.out.println("DT output Stream is :"+dtsOutput);
System.out.println("Tv input Stream is :"+socket.getInputStream());
System.out.println("DT input Stream is :"+socket2.getInputStream());
tvsInput = new ObjectInputStream(socket2.getInputStream());
System.out.println("Tv input Stream is 2 :"+tvsInput);
dtsInput = new ObjectInputStream(socket2.getInputStream());
System.out.println("DT input Stream is :"+dtsInput);
System.out.println("Tv input Stream is :"+tvsInput);
// TODO Auto-generated constructor stub
}
catch (IOException e)
{
System.out.println("Exception in PH");
e.printStackTrace();
}
}
#Override
public void run()
{
try
{
//dtsInput = new ObjectInputStream(dtsocket.getInputStream());
System.out.println("DT socket :"+dtsInput);
if(dtsInput!=null){
RemoteAccess dtMsg = (RemoteAccess) dtsInput.readObject();
if(dtMsg !=null){
// write to tvscoket
System.out.println("I am here in Pair Handler");
sendTOTv(dtMsg);
}
}
// tvsInput = new ObjectInputStream(tvsocket.getInputStream());
System.out.println("TV socket :"+tvsInput);
if(tvsInput!=null){
RemoteAccess tvmsg = (RemoteAccess) tvsInput.readObject();
if(tvmsg !=null){
// write to dtsocket
sendToDT(tvmsg);
}
}
}
catch (IOException e)
{
e.printStackTrace();
System.out.println("Exception found while msg");
}
catch(ClassNotFoundException e2) {
e2.printStackTrace();
}
}
private void sendToDT(RemoteAccess tvmsg) {
// TODO Auto-generated method stub
// if Client is still connected send the message to it
if(!dtsocket.isConnected())
{
closeDtSocket();
}
try {
dtsOutput.writeObject(tvmsg);
}
catch(IOException e) {
System.out.println("Failed to deliver msg");
}
}
private void closeDtSocket() {
try {
if(dtsOutput != null) dtsOutput.close();
}
catch(Exception e) {
e.printStackTrace();
}
try {
if(dtsInput != null) dtsInput.close();
}
catch(Exception e) {
e.printStackTrace();
};
try {
if(dtsocket != null) dtsocket.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
private void closeTvSocket() {
try {
if(tvsOutput != null) tvsOutput.close();
}
catch(Exception e) {
e.printStackTrace();
}
try {
if(tvsInput != null) tvsInput.close();
}
catch(Exception e) {
e.printStackTrace();
};
try {
if(tvsocket != null) tvsocket.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
private void sendTOTv(RemoteAccess dtMsg) {
// TODO Auto-generated method stub
if(!tvsocket.isConnected())
{
closeTvSocket();
}
try {
tvsOutput.writeObject(dtMsg);
}
catch(IOException e) {
System.out.println("Failed to deliver msg");
}
}
}
RemoteAccess.java
package customChat;
import java.io.File;
import java.io.Serializable;
class RemoteAccess implements Serializable {
private static final long serialVersionUID = 1L;
private long to;
private long from;
private File file;
private String msg;
private int x ;
private int y;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
RemoteAccess(){
}
RemoteAccess(long to,long from)
{
this.to=to;
this.from=from;
}
RemoteAccess(long to,long from,File file)
{
this.to=to;
this.from=from;
this.file=file;
}
RemoteAccess(long to,long from,int x,int y)
{
this.to=to;
this.from=from;
this.x=x;
this.y=y;
}
RemoteAccess(long to,long from,String msg)
{
this.to=to;
this.from=from;
this.msg=msg;
}
public File getFile() {
return file;
}
public void setFile(File file) {
this.file = file;
}
public long getTo() {
return to;
}
public void setTo(long to) {
this.to = to;
}
public long getFrom() {
return from;
}
public void setFrom(long from) {
this.from = from;
}
}
I supposed you want to customize client1 and client2. So you should create a class for each one :
public class Client1 extends Socket {
public Client1() {
super();
}
//Add stuff to customize
}
public class Client2 extends Socket {
public Client2() {
super();
}
//Add stuff to customize
}
Then create your class that contains your two sockets :
public class ClientDialog {
private Client1 client1;
private Client2 client2;
public ClientDialog() {
client1 = new Client1();
client2 = new Client1();
}
//Dialog between client
}
This is the SocketServer code that generates a server thread
public class ProcessorCorresponder {
protected final static Logger logger = LogManager.getLogger( ProcessorCorresponder.class );
private static int port = Integer.parseInt(PropertiesLoader.getProperty("appserver.port") == null ? "666" : PropertiesLoader.getProperty("appserver.port"));
private static int maxConnections = Integer.parseInt(PropertiesLoader.getProperty("appserver.maxconnections") == null ? "666" : PropertiesLoader.getProperty("appserver.maxconnections"));
public static void main(String[] args) {
logger.info("Starting server .. "
+ "[port->" + port
+ ",databaseName->" + databaseName + "]");
try (ServerSocket listener = new ServerSocket();) {
listener.setReuseAddress(true);
listener.bind(new InetSocketAddress(port));
Socket server;
int i = 0;
while((i++ < maxConnections) || (maxConnections == 0)) {
server = listener.accept();
logger.debug(
"New Thread listening on " + server.getLocalAddress().toString() + ":" + server.getLocalPort()
+ ", initiated from IP => " + server.getInetAddress().toString() + ":" + server.getPort()
);
MySocketServer socSrv = new MySocketServer (server);
Thread t = new Thread( socSrv );
t.start();
}
} catch (Exception ex) {
logger.error("Error in ProcessorInterface", ex);
}
}
}
Server code: This is a thread to handle one connection, there is a program that monitors a serversocket and spins off request threads as needed.
public class MySocketServer implements Runnable {
protected final static Logger logger = LogManager.getLogger(MySocketServer.class);
private final Socket server;
// because we are using threads, we must make this volatile, or the class will
// never exit.
private volatile boolean shouldContinue = true;
private StringBuffer buffHeartbeatMessage = new StringBuffer().append((char) 0).append((char) 0).append((char) 0)
.append((char) 0).append((char) 0).append((char) 0);
private Heartbeat heartbeat = new Heartbeat(/* 60 */3000, buffHeartbeatMessage.toString());
public MySocketServer(Socket server) {
this.server = server;
}
#Override
public void run() {
try (BufferedReader in = new BufferedReader(new InputStreamReader(this.server.getInputStream()));
BufferedOutputStream out = new HeartbeatBufferedOutputStream(this.server.getOutputStream(),
heartbeat)) {
final StreamListener listener = new StreamListener(in);
listener.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
if (event.getID() == ActionEvent.ACTION_PERFORMED) {
if (event.getActionCommand().equals(StreamListener.ERROR)) {
logger.error("Problem listening to stream.");
listener.setShouldContinue(false);
stopRunning();
} else {
String messageIn = event.getActionCommand();
if (messageIn == null) { // End of Stream;
stopRunning();
} else { // hey, we can do what we were meant for
logger.debug("Request received from client");
// doing stuff here
...
// done doing stuff
logger.debug("Sending Client Response");
try {
sendResponse(opResponse, out);
} catch (Exception ex) {
logger.error("Error sending response to OP.", ex);
}
}
}
}
}
});
listener.start();
while (shouldContinue) {
// loop here until shouldContinue = false;
// this should be set to false in the ActionListener above
}
heartbeat.setShouldStop(true);
return;
} catch (Exception ex) {
logger.error("Error in ESPSocketServer", ex);
return;
}
}
private void stopRunning() {
shouldContinue = false;
}
private void sendResponse(ClientResponse opResponse, BufferedOutputStream out) throws Exception {
logger.debug("Before write");
out.write(opResponse.getResponse().getBytes());
logger.debug("After write. Before flush");
out.flush();
logger.debug("After flush");
// this log message is in my logs, so I know the message was sent
}
}
My StreamListener class.
public class StreamListener extends Thread {
protected final static Logger logger = LogManager.getLogger(StreamListener.class);
public final static String ERROR = "ERROR";
private BufferedReader reader = null;
private List<ActionListener> actionListeners = new ArrayList<>();
private boolean shouldContinue = true;
public StreamListener(BufferedReader reader) {
this.reader = reader;
}
#Override
public void run() {
while (shouldContinue) {
String message;
try {
// client blocks here and never receives message
message = reader.readLine();
ActionEvent event = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, message);
fireActionPerformed(event);
} catch (IOException e) {
e.printStackTrace();
ActionEvent event = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, ERROR);
fireActionPerformed(event);
}
}
}
public void setShouldContinue(boolean shouldContinue) {
this.shouldContinue = shouldContinue;
}
public boolean getShouldContinue() {
return shouldContinue;
}
public boolean addActionListener(ActionListener listener) {
return actionListeners.add(listener);
}
public boolean removeActionListener(ActionListener listener) {
return actionListeners.remove(listener);
}
private void fireActionPerformed(ActionEvent event) {
for (ActionListener listener : actionListeners) {
listener.actionPerformed(event);
}
}
}
My Heartbeat class
public class Heartbeat extends Thread {
private BufferedOutputStream bos = null;
private int beatDelayMS = 0;
private String message = null;
private boolean shouldStop = false;
public Heartbeat(int beatDelayMS, String message) {
this.beatDelayMS = beatDelayMS;
this.message = message;
setDaemon(true);
}
#Override
public void run() {
if (bos == null) { return; }
while(!shouldStop) {
try {
sleep(beatDelayMS);
try {
bos.write(message.getBytes());
bos.flush();
} catch (IOException ex) {
// fall thru
}
} catch (InterruptedException ex) {
if (shouldStop) {
return;
}
}
}
}
public void setBufferedOutputStream(BufferedOutputStream bos) {
this.bos = bos;
}
public BufferedOutputStream getBufferedOutputStream() {
return bos;
}
public void setShouldStop(boolean shouldStop) {
this.shouldStop = shouldStop;
}
public boolean getShouldStop() {
return shouldStop;
}
}
My HeartbeatBufferedOutputStream
public class HeartbeatBufferedOutputStream extends BufferedOutputStream {
private Heartbeat heartbeat = null;
public HeartbeatBufferedOutputStream(OutputStream out, Heartbeat heartbeat) {
super(out);
this.heartbeat = heartbeat;
this.heartbeat.setBufferedOutputStream(this);
heartbeat.start();
}
#Override
public synchronized void flush() throws IOException {
super.flush();
heartbeat.interrupt();
}
}
And finally here is the "Client" class
public class Mockup extends Thread {
protected final static Logger logger = LogManager.getLogger(Mockup.class);
// because we are using threads, we must make this volatile, or the class will
// never exit.
private volatile boolean shouldContinue = true;
public static void main(String[] args) {
new Mockup().start();
}
#Override
public void run() {
try (Socket socket = new Socket("localhost", 16100);
BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream());
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));) {
final StreamListener listener = new StreamListener(in);
listener.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
if (event.getID() == ActionEvent.ACTION_PERFORMED) {
if (event.getActionCommand().equals(StreamListener.ERROR)) {
logger.error("Problem listening to stream.");
listener.setShouldContinue(false);
stopRunning();
} else {
String messageIn = event.getActionCommand();
if (messageIn == null) { // End of Stream;
stopRunning();
} else { // hey, we can do what we were meant for
// convert the messageIn to an OrderPower request, this parses the information
logger.info("Received message from server. [" + messageIn + "].");
}
}
}
}
});
listener.start();
StringBuffer buff = new StringBuffer("Some message to send to server");
logger.info("Sending message to server [" + buff.toString() + "]");
out.write(buff.toString().getBytes());
out.flush();
boolean started = false;
while (shouldContinue) {
if (!started) {
logger.debug("In loop");
started = true;
}
// loop here until shouldContinue = false;
// this should be set to false in the ActionListener above
}
logger.info("Exiting Mockup");
return;
} catch (Exception ex) {
logger.error("Error running MockupRunner", ex);
}
}
private void stopRunning() {
shouldContinue = false;
}
}
I have confirmed from logging messages that the Server sends a message to the BufferedOutputStream, and is flushed, but the Client logs indicate that it is blocked on the reader.readLine() and never gets the message.
You are reading lines but you are never writing lines. Add a line terminator to what you send.
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 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.