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.
Related
I am currently trying to set up an App for an Android Device, which can communicate with Devices in the same Network via TCP connection. Said Devices run on Windows and therefore I created a simple C# TCP Client program to connect to the TCP Server. The connection gets established when the Server App is already running and a Client tries to connect to it. Both sides (Server/Client) confirm that the connection got established. When I send data from the server via DataOutputStream back to the client, the client confirms, that he got the message. But when I try to send data from the client and try to read it on the server via InputStreamReader the server never reacts to incoming messages.
Below lies the Java Android server code:
public class TCPServer {
public enum ServerCommands { TURN_OFF }
private static ServerSocket serverSocket;
private static final Handler HANDLER = new Handler(Looper.getMainLooper());
private static final int SERVERPORT = 5040;
private static final HashMap<InetAddress, ServerClientCommunicationThread> connectedClientThreads = new HashMap<>();
private interface OnUpdateUIListener {
void onShowStatus(String status);
}
private static OnUpdateUIListener listener;
public static void InitServer(Consumer<String> showStatus) {
listener = new OnUpdateUIListener() {
#Override
public void onShowStatus(String status) {
// Use the handler so we're not trying to update the UI from the bg thread
HANDLER.post(new Runnable(){
#Override
public void run(){
showStatus.accept(status);
}
});
}
};
Thread serverThread = new Thread(new ServerThread());
serverThread.start();
}
public static void OnStop(){
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void SendMessageToClient(InetAddress clientIP, ServerCommands action){
ServerClientCommunicationThread clientThread = connectedClientThreads.get(clientIP);
listener.onShowStatus("Trying to send Data to client!");
if (clientThread != null)
clientThread.getHandler().sendEmptyMessage(action.ordinal());
}
private static class ServerThread implements Runnable {
public void run() {
Socket socket = null;
try {
serverSocket = new ServerSocket(SERVERPORT);
} catch (IOException e) {
e.printStackTrace();
}
boolean error = false;
while (!Thread.currentThread().isInterrupted() && !error) {
try {
listener.onShowStatus("Start listening for clients!");
socket = serverSocket.accept();
listener.onShowStatus("Found client: " + socket.getInetAddress());
ClientServerCommunicationThread clientCommThread = new ClientServerCommunicationThread(socket);
new Thread(clientCommThread).start();
ServerClientCommunicationThread serverCommThread = new ServerClientCommunicationThread("CommThread", socket);
new Thread(serverCommThread).start();
connectedClientThreads.put(serverCommThread.clientSocket.getInetAddress(), serverCommThread);
} catch (Exception e) {
listener.onShowStatus("Could not establish client connection: " + e);
error = true;
}
}
}
}
private static class ServerClientCommunicationThread extends HandlerThread {
private DataOutputStream outputStream;
private Socket clientSocket;
private Handler commHandler;
public ServerClientCommunicationThread(String name, Socket clientSocket) {
super(name);
try {
this.clientSocket = clientSocket;
this.outputStream = new DataOutputStream(clientSocket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
listener.onShowStatus("ERROR: could not open ReaderStream: " + e);
}
}
#SuppressLint("HandlerLeak")
#Override
protected void onLooperPrepared(){
commHandler = new Handler(){
#Override
public void handleMessage(Message msg){
try {
outputStream.write(msg.what);
listener.onShowStatus("Sent action: " + msg.what);
outputStream.flush();
}
catch(Exception e){
listener.onShowStatus("Could not send data to client: " + clientSocket.getInetAddress() + " " + e);
}
}
};
listener.onShowStatus("Start Server Communication Thread");
}
public Handler getHandler(){
return commHandler;
}
}
private static class ClientServerCommunicationThread extends Thread {
private BufferedReader input;
private final Socket clientSocket;
public ClientServerCommunicationThread(Socket clientSocket){
super();
this.clientSocket = clientSocket;
try{
this.input = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
listener.onShowStatus("ERROR: could not open ReaderStream: " + e);
}
}
#Override
public void run(){
listener.onShowStatus("Start Client Communication Thread");
boolean connectionStable = true;
while (!Thread.currentThread().isInterrupted() && connectionStable) {
try {
String read = input.readLine();
//It never reaches this debug message!
listener.onShowStatus("Received message: " + read);
} catch (IOException e) {
e.printStackTrace();
listener.onShowStatus("ERROR: could not read message: " + e);
connectionStable = false;
}
}
try {
input.close();
clientSocket.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
Below lies my C# client code.
I am using the SuperSimpleTCP library for my C# code.
namespace SimpleTCPProgram
{
internal class TCPClient
{
private static SimpleTcpClient tcpClient;
private static int udpPort = 5041;
private static int tcpPort = 5040;
private static string macAddr;
enum ServerCommands { TURN_OFF = 0 }
// Main Method
static public void Main(String[] args)
{
InitTCPClient("192.168.1.4");
Console.ReadKey();
tcpClient.Send("Hello there");
Console.WriteLine("Sent data: " + tcpClient.Statistics.SentBytes.ToString());
Console.ReadKey();
}
private static void InitTCPClient(string serverIP)
{
try
{
tcpClient = new SimpleTcpClient(serverIP + ":" + tcpPort);
tcpClient.Events.Connected += Events_Connected;
tcpClient.Events.Disconnected += Events_Disconnected;
tcpClient.Events.DataReceived += Events_DataReceived;
tcpClient.Connect();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
private static void Events_Connected(object sender, ConnectionEventArgs e)
{
Console.WriteLine("Connected to Server: " + e.IpPort);
}
private static void Events_Disconnected(object sender, ConnectionEventArgs e)
{
}
private static void Events_DataReceived(object sender, SuperSimpleTcp.DataReceivedEventArgs e)
{
string dataString = Encoding.UTF8.GetString(e.Data);
Console.WriteLine("Received Data: " + dataString);
ServerCommands serverCommand = (ServerCommands)int.Parse(dataString);
switch (serverCommand)
{
case ServerCommands.TURN_OFF:
var psi = new ProcessStartInfo("shutdown", "/s /t 0");
psi.CreateNoWindow = true;
psi.UseShellExecute = false;
Process.Start(psi);
break;
default:
break;
}
}
}
}
Wireshark seems to confirm that the message has been sent to the server.
It even catches a message sent back by the server to the client in response.
I am testing this on a test-router which doesn't have internet access and no firewall active.
My server app has the following permissions:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" tools:ignore="ManifestOrder"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
TLDR: My Android java server doesn't get any C# client messages sent via TCP connection.
I am trying to create for a university project a server / slave / client project.
The server should open 2 ports, one port will be for the connection of the slave and another port for the client.
I have setup 2 threads 1 for the client and another for the slave. The client should sent random numbers to server and server should forward randomly those numbers to slave instances. The slave should check if the current number exist on their list and if it's not available to store it, otherwise they should sent a message to server that the number already exist.
Then I created the client thread which consist of 2 threads, one for sending the numbers to server and another thread to read messages coming from the server.
There is something wrong with the code of the PrintWriter, I cannot make it to send the numbers to server when the code is inside the thread. If I move the code on the main and cancel the thread the messages are being sent without any issue.
What could be the issue for this?
Below is the current code from server (master) and the client.
public class Client {
private static final int NUMBERS = 50;
private static final int AMPLITUDE = 100;
private static int masterPort;
public Client(int port) {
this.masterPort = port;
}
public static void main(String[] args) throws IOException{
String serverHostname = "127.0.0.1";
System.out.println("Αναμονή για σύνδεση στον σέρβερ " + serverHostname + " στην πόρτα 30091.");
Socket echoSocket = null;
BufferedReader in = null;
try {
echoSocket = new Socket(serverHostname, 18889);
in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Δεν μπορεί να πραγματοποιηθεί σύνδεση με τον σέρβερ: " + serverHostname);
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to: " + serverHostname);
System.exit(1);
}
ClientOut clientOut = new ClientOut(echoSocket);
clientOut.start();
ClientIn clientIn = new ClientIn(in);
clientIn.start();
in.close();
echoSocket.close();
}
public static class ClientOut extends Thread {
private PrintWriter out;
public ClientOut(Socket echoSocket) throws IOException {
this.out = new PrintWriter(echoSocket.getOutputStream(), true);
}
#Override
public void run() {
System.out.println("Ο client συνδέθηκε!");
Random rnd = new Random();
try {
for (int i=0; i<NUMBERS; i++) {
int num = rnd.nextInt(AMPLITUDE);
System.out.println(num);
out.println(num);
TimeUnit.SECONDS.sleep(1);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
out.close();
}
}
public static class ClientIn extends Thread {
private BufferedReader in;
public ClientIn(BufferedReader in) {
this.in = in;
}
#Override
public void run() {
}
}
}
public class Master {
private int slavePort;
private int clientPort;
private SlaveThread slaveThread;
private ClientThread clientThread;
private boolean running = false;
public static int slaveConnected; // Slave connection counter
public Master(int slavePort, int clientPort) {
this.slavePort = slavePort;
this.clientPort = clientPort;
this.slaveConnected = 0;
public void startServer() {
try {
this.slaveThread = new SlaveThread(slavePort);
this.clientThread = new ClientThread(clientPort);
System.out.println( "Αναμονή για σύνδεση client / slave" );
slaveThread.start();
clientThread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
public void stopServer() {
running = false;
this.slaveThread.interrupt();
this.clientThread.interrupt();
}
class SlaveThread extends Thread {
private ServerSocket slaveSocket;
SlaveThread(int slavePort) throws IOException {
this.slaveSocket = new ServerSocket(slavePort);
}
#Override
public void run() {
running = true;
while (running) {
try {
// Call accept() to receive the next connection
Socket slSocket = slaveSocket.accept();
System.out.println("Δημιουργήθηκε μια νέα σύνδεση Slave");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class ClientThread extends Thread {
private ServerSocket clientSocket;
ClientThread(int clientPort) throws IOException {
this.clientSocket = new ServerSocket(clientPort);
}
#Override
public void run() {
running = true;
while (running) {
try {
Socket clSocket = clientSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(clSocket.getInputStream()));
System.out.println("Δημιουργήθηκε μια νέα σύνδεση Client");
String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println("Client: " + inputLine);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
Master server = new Master( 30091, 18889);
server.startServer();
// Automatically shutdown in 1 minute
try {
Thread.sleep( 60000 );
} catch(Exception e) {
e.printStackTrace();
}
server.stopServer();
}
I found the solution.
The Socket should be created on the Client Thread constructor and not to be passed as reference.
So the client should be
public class Client {
private static final int NUMBERS = 50;
private static final int AMPLITUDE = 100;
private static int masterPort;
public Client(int port) {
this.masterPort = port;
}
public static void main(String[] args) throws IOException{
String serverHostname = "127.0.0.1"; //Ορίζουμε την διεύθυνση που είναι ο σέρβερ
System.out.println("Αναμονή για σύνδεση στον σέρβερ " + serverHostname + " στην πόρτα 30091.");
ClientOut clientOut = new ClientOut(serverHostname);
clientOut.start();
ClientIn clientIn = new ClientIn(serverHostname);
clientIn.start();
}
public static class ClientOut extends Thread {
private Socket echoSocket;
private PrintWriter writer;
ClientOut(String serverHostname) throws IOException {
this.echoSocket = new Socket(serverHostname, 18889);
this.writer = new PrintWriter(echoSocket.getOutputStream(), true);;
}
#Override
public void run() {
System.out.println("Ο client συνδέθηκε!");
Random rnd = new Random();
try {
for (int i=0; i<NUMBERS; i++) {
int num = rnd.nextInt(AMPLITUDE);
System.out.println(num);
writer.println(num);
TimeUnit.SECONDS.sleep(1);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
writer.close();
}
}
I'am creating application to making screenshots via LAN. Server is
listening for clients. When client is connect, new thread is created and it shoud be added to a list. Admin on server can pick client from list, make screenshot on its computer and screenshot is sent to server. The problem is the list. How to make this list available in many places in app and it was always synchronized with all components that use it ?
I am using JavaFX. I readed about SimpleListProperty, but the problem was "how to use this instance in server thread?". I've tried with singletone variations, dependencies injection like Guice, Ignite, Spring, but it was generated many troubles and finally doesn't work :(
Server implementation
public class SocketServer extends Thread {
private ServerSocket serverSocket;
#Override
public void run() {
startServer();
}
private void startServer() {
try {
serverSocket = new ServerSocket(2345);
} catch (IOException e) {
e.printStackTrace();
}
while (true) {
try {
new EchoClientHandler(serverSocket.accept()).run();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void stopServer() {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public class EchoClientHandler extends Thread {
private Socket clientSocket;
private PrintWriter out;
private BufferedReader in;
public EchoClientHandler(Socket socket) {
this.clientSocket = socket;
}
#Override
public void run() {
try {
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
//there shoud be somethink like:
// list.add(this);
}
public void close() {
try {
in.close();
out.close();
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//Getters and setters
MainController
public class MainController {
#FXML
private LogPaneController logPaneController;
#FXML
private ConnectionPaneController connectionPaneController;
#FXML
private ButtonsPaneController buttonsPaneController;
private Connector connectorImpl;
public void initialize() {
createConnector();
}
private void createConnector() {
ObservableList<Client> observableList = connectionPaneController.getConnectedClientsTable().getItems();
connectorImpl.setClientSimpleListProperty(observableList);
}
Connector
public class ConnectorImpl implements Connector {
private List<SocketServer.EchoClientHandler> clientsThreads;
private SimpleListProperty<Client> clientSimpleListProperty;
public ConnectorImpl() {
}
public static Client parseThreadToClient(SocketServer.EchoClientHandler clientThread) {
Socket socket = clientThread.getClientSocket();
PrintWriter out = clientThread.getOut();
BufferedReader in = clientThread.getIn();
return new Client(socket, out, in);
}
#Override
public void connectNewClient(SocketServer.EchoClientHandler clientThread) {
clientsThreads.add(clientThread);
clientSimpleListProperty.add(parseThreadToClient(clientThread));
}
//Getters and setters
}
App view
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.
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.