I have a chat program. Now the code works for communicate between client and server via command line. But it gives an exception (java.net.SocketException: Socket is closed) while running. Please help me to fix that problem.
In a java chat program,how will the communication be implemented between client and server?
ie.
client<-->server (between server and client)
or
client A<-->server<-->client B (server act as a bridge between two clients)
Is the 2 way communication can be implemented through a single socket?
Are there any other methods ?
How to communicate more than one client simultaneously?
server code
class Server
{
ServerSocket server;
Socket client;
public Server()
{
try
{
server = new ServerSocket(2000);
System.out.println("\tServer Started..........");
while (true)
{
client = server.accept();
Send objsend = new Send(client);
Recive objrecive = new Recive(client);
//client.close();
}
}
catch (Exception e)
{
System.out.println("Exception4 " + e);
}
}
public static void main(String arg[])
{
new Server();
}
}
class Recive implements Runnable
{
Socket client;
public Recive(Socket client1)
{
client=client1;
Thread trsend=new Thread(this);
trsend.start();
}
public void run()
{
ObjectInputStream ois;
Message M=new Message();
try
{
ois = new ObjectInputStream(client.getInputStream());
M = (Message)ois.readObject();
M.display();
ois.close();
}
catch (Exception e)
{
System.out.println("Exception1 " + e);
}
}
}
class Send implements Runnable
{
Socket client;
public Send(Socket client1)
{
client=client1;
Thread trrecive=new Thread(this);
trrecive.start();
}
public void run()
{
Message M=new Message();
InputStreamReader isr=new InputStreamReader(System.in);
BufferedReader br=new BufferedReader(isr);
try
{
System.out.println("Me(server)");
M.strmessage=br.readLine();
ObjectOutputStream oos=new ObjectOutputStream(cli ent.getOutputStream());
oos.writeObject((Message)M);
oos.flush();
oos.close();
}
catch (Exception e)
{
System.out.println("Exception " + e);
}
}
}
client code
class Client
{
public static void main(String arg[])
{
try
{
Send objsend=new Send();
Recive objrecive=new Recive();
}
catch(Exception e)
{
System.out.println("Exception "+e);
}
}
}
class Send implements Runnable
{
public Send()
{
Thread trsend=new Thread(this);
trsend.start();
}
public void run()
{
try
{
Message M=new Message();
InputStreamReader isr=new InputStreamReader(System.in);
BufferedReader br=new BufferedReader(isr);
while(true)
{
System.out.println("Me(client)");
M.strmessage=br.readLine();
Socket client=new Socket("localhost",2000);
ObjectOutputStream oos=new ObjectOutputStream(client.getOutputStream());
oos.writeObject((Message)M);
oos.flush();
oos.close();
}
}
catch(Exception e)
{
System.out.println("Exception "+e);
}
}
}
class Recive implements Runnable
{
public Recive()
{
Thread trrecive=new Thread(this);
trrecive.start();
}
public void run()
{
try
{
while(true)
{
Socket client=new Socket("localhost",2000);
ObjectInputStream ois=new ObjectInputStream(client.getInputStream());
Message CNE=(Message)ois.readObject();
CNE.display();
ois.close();
}
}
catch(Exception e)
{
System.out.println("Exception "+e);
}
}
}
First of all, don't close the streams in every run().
Secondly, check whether port for server which you are using is free.
This program makes your pc both host and server.
import java.io.IOException;
import java.net.*;
public class ClientServer {
static byte[] buffer = new byte[100];
private static void runClient() throws IOException {
byte buffer[] = new byte[100];
InetAddress address = InetAddress.getLocalHost();
DatagramSocket ds=new DatagramSocket();
int pos = 0;
while (pos<buffer.length) {
int c = System.in.read();
buffer[pos++]=(byte)c;
if ((char)c =='\n')
break;
}
System.out.println("Sending " + pos + " bytes");
ds.send(new DatagramPacket(buffer, pos, address, 3000));
}
private static void runServer() throws IOException {
InetAddress address = InetAddress.getLocalHost();
DatagramSocket ds = new DatagramSocket(3000, address);
DatagramPacket dp = new DatagramPacket(buffer, buffer.length);
ds.receive(dp);
String s=new String(dp.getData(),0,dp.getLength());
System.out.print(s);
}
public static void main(String args[]) throws IOException {
if (args.length == 1) {
runClient();
} else {
runServer();
}
}
}
also follow this link
There could be multiple places where the exception could be thrown. Without a stack trace it is difficult to state so accurately, as to the cause of failure.
But the root cause, is essentially due to the fact that you are closing the InputStream of the socket in your Receiver threads after reading a message, and closing the OutputStream of the socket in your Sender threads after sending a message. Closing either of these streams will automatically close the socket, so you if attempt to perform any further operation on it, a SocketException will be thrown.
If you need to ensure that your server and client do not shutdown in such an abrupt manner, you'll have to keep reading the InputStream (until you get a special message to shutdown, for instance). At the same time, you'll also have to keep writing to the OutputStream. Two-way communication is definitely possible, and the posted code is capable of the same (if the socket remains open).
If you have to handle multiple clients, you'll need multiple reader and writer threads on the server, each listening on an instance of a Socket returned from ServerSocket.accept(); in simpler words, you need a reader-writer pair listening on a distinct socket on the server for each client. At the moment, multiple clients can connect to the Server, as each incoming connection is provided its own client Socket object on the Server, that is provided to individual reader and writer threads. The main Server thread can continue to receive incoming connections and delegate the actual work to the reader-writer pairs.
chat programms normaly have a server through which all communication goes. The reason is that other wise every client needs to know how to reach every other client. And that doesn't work in the general case.
So you'll have a server, every client registers and talks with the server, which will forward messages to other clients.
Mostly communication is done via HTTP cause this is likely to go through firewalls and proxies. You probably want to read up on long polling if you are planning for anything serious.
Related
hey I'm writing a simple code with a server socket and multiple clients which the server gets every client's username and stores them in a hashmap.the server accepts a socket client and the client enters the username but again the server accept the same socket client and it wants its username and the code stops here.i want it to work for multiple clients not just one.
server class:
public class Server implements Serializable{
// [..]
public void serverConnect() throws IOException, ClassNotFoundException
{
listener = new ServerSocket(9090);
System.out.println("Server is running...");
while (true)
{
System.out.println("Waiting ...");
socket=listener.accept();
for (Socket socket:socketList.keySet())
{
if (this.socket==socket)
{
checkSocket=false;
}
}
if (checkSocket)
{
socketList.put(socket,socketNumber);
System.out.println("Client is connected");
inputReader = new InputStreamReader(socket.getInputStream());
reader = new BufferedReader(inputReader);
user = reader.readLine();
Server.userList.add(user);
socketNumber++;
}
checkSocket=true;
}
}
}
client class:
public class Client {
public Client() {
}
public void clientConnect() throws UnknownHostException, IOException {
System.out.println("enter your username");
Scanner scanner = new Scanner(System.in);
String msg = scanner.nextLine();
Socket socket = new Socket("localhost", 9090);
PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
writer.println(msg);
}
}
In principle you have the workings of single thread server (which means it can accept only one client connection at a time). The main issue is that you have over-complicated how you receive a connection.
You can simplify your current code by dealing by moving the client connection socket and readers into the local scope and dealing with the socket directly.
public void serverConnect() throws IOException {
listener = new ServerSocket(9090);
System.out.println("Server is running...");
while (true) {
System.out.println("Waiting ...");
Socket socket = listener.accept();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
String user = reader.readLine();
Server.userList.add(user);
} catch (IOException ignore) {
} finally {
socket.close();
}
}
}
As you can see you don't need to keep hold of the socket beyond reading the value sent. If you are only expecting the one line of data from the client, you should also close the socket otherwise the client can hold the server hostage by not sending any data until the socket timeout is reached.
Further to this you also want to wrap the code inside the while loop with a try/catch block to prevent an exception terminating the server.
As I mentioned in the opening paragraph this code works as a single threaded server and it can only respond to a single request at a time. If you want to accept and process multiple requests you will need to spawn a new thread to handle the response. I would recommend constructing your code as below but for the sake of brevity you could do something like below:
public void serverConnect() throws IOException {
int MAX_WORKERS = 100;
ExecutorService service = Executors.newFixedThreadPool(MAX_WORKERS);
ServerSocket listener = new ServerSocket(9090);
System.out.println("Server is running...");
while (true) {
System.out.println("Waiting ...");
Socket socket = listener.accept();
service.submit(() -> {
System.out.println("Client is connected");
try {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
String user = reader.readLine();
Server.userList.add(user);
} finally {
socket.close();
}
} catch (Throwable ignore) {
}
});
}
}
So all that is happening above is that we are creating a thread pool of 100 threads using the ExecutorService. This means in theory we can accept 100 concurrent connections.
When a connection is accepted, we submit the socket and worker code to a thread which means that the main thread can return to listening for a new connections.
I have created a server-client project where the server keeps listening and prints the information. However, when i shutdown the client, the server remains open. The problem is that I need to insert this into another application, and, if the server does not close at first, the application will not open unless i kill the process in that port (but this is not an option to me). What should I do to properly close the server once the client disconnects?
Here is the code:
Server:
public class Server {
public static void main(String[] args) {
Connection conn = new Connection();
new Thread(conn).start();
}
private static class Connection implements Runnable {
#Override
public void run() {
try (ServerSocket serverSocket = new ServerSocket(5005)) {
Socket socket = serverSocket.accept();
listener(socket);
} catch (IOException ex) {
ex.printStackTrace();
}
}
private void listener(Socket socket) throws IOException {
DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
DataInputStream inputStream = new DataInputStream(socket.getInputStream());
boolean alive = true;
while (alive) {
try {
outputStream.writeUTF(new Scanner(System.in).nextLine());
System.out.println(inputStream.readUTF());
} catch (IOException ex) {
ex.printStackTrace();
alive = false;
}
}
}
}
}
Client:
public class Client {
public static void main(String[] args) {
try (Socket socket = new Socket("localhost", 5005)) {
DataInputStream inputStream = new DataInputStream(socket.getInputStream());
DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
while (socket.isConnected()) {
System.out.println("Incoming data: " + inputStream.readUTF());
outputStream.writeUTF(new Scanner(System.in).nextLine());
outputStream.flush();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
Since now, thank you very much!
The thing that force the system wait and not close is this line at your Server.java :
outputStream.writeUTF(new Scanner(System.in).nextLine());
Once it starts waiting the user input, it waits forever along the life time of the instance although your client is disconnected.
So what you can do ? You can create another thread that makes periodic "ENTER" inputs (if you insist using new Scanner(System.in)) for example input per 5 seconds. After the enter, or any other meaningful input, if you decide this is not from your client, don't write it to the client and wait user input again (if your client still connected !). If your client is not connected, just finish your loop.
Please check Java Robot class and this example
I'm new in Java Sockets, I have seen so many examples but I can't understand how to pass an argument from server to client and vice versa. My destination is to pass an Object that's why I'm using Object I/O Stream.
I have to classes Server and Player.
public class Server extends Thread{
public static final int TEST = 165;
ServerSocket serverSocket;
InetAddress address;
Player playerWhite;
public Server() {
start();
}
#Override
public void run() {
try
{
address = InetAddress.getLocalHost();
serverSocket = new ServerSocket(6000);
playerWhite = new Player();
System.out.println("server waits for players");
playerWhite.socket = serverSocket.accept();
playerWhite.start();
sendTestMessage(playerWhite);
}
catch (IOException ex)
{
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void sendTestMessage(Player player) throws IOException
{
ObjectOutputStream testToClient = new ObjectOutputStream(player.socket.getOutputStream());
testToClient.write(TEST);
testToClient.flush();
}
And the Player class:
public class Player extends Thread {
Socket socket;
Player() throws IOException
{
socket = new Socket(InetAddress.getLocalHost(), 6000);
}
#Override
public void run() {
try {
listenTestStream();
}
catch (IOException | ClassNotFoundException ex)
{
Logger.getLogger(CheckerPlayer.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void listenTestStream() throws IOException, ClassNotFoundException
{
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
int message = ois.readInt();
//To test
System.out.println("Server listened: " + message);
}
I execute it as create a Server object in the other class.
When I have testing this application I saw that sometimes client is faster than Server. Is it possible to make him "wait" for server response?
Thanks for your response.
EDIT 1: PROBLEM SOLUTION:
From outside we should create:
Player player = new Player(); // (class player extends from Thread)
player.start();
and delete the Player variable - is not necessary, we need only Socket so:
Server:
Socket playerWhiteSocket
public void run() {
try
{
serverSocket = new ServerSocket(PORT);
playerWhiteSocket = serverSocket.accept();
sendMessage(playerWhiteSocket, "Hello");
}
catch(IOException | ClassNotFoundException ex)
{}
public void sendMessage(Socket socket, String message) throws IOException
{
ObjectOutputStream testToClient = new ObjectOutputStream(socket.getOutputStream());
testToClient.writeObject(message);
testToClient.flush();
}
In Player class we need get method:
public String receiveMessage() throws IOException, ClassNotFoundException
{
//socket is a variable get from Player class socket = new Socket("severHost", PORT);
ObjectInputStream messageFromServer = new ObjectInputStream(socket.getInputStream());
String message = (String) messageFromServer.readObject();
return message;
}
I would recomment doing this public void start(){
try {
ServerSocket = new ServerSocket(this.port,10,this.localAddress);
// set timeout if you want
//this.clientServerSocket.setSoTimeout(timeout);
// infinity loop
while(true)
{
//wait for a client connection
Socket socket = ServerSocket.accept();
// start thread for every new client
Thread t = new Thread(new AcceptClients(this.socket));
t.start();
System.out.println(L"new client connected");
// call garbage collector and hope for the best
System.gc();
}
} catch (IOException e) {
System.out.println("IO Error");
e.printStackTrace();
}
}
and then in another class
public class AcceptClients implements Runnable{
// socket
private Socket socket;
public AcceptClients (Socket socket){
this.socket = socket;
}
#Override
public void run() {
// what happens if a client connect
}
}
I always use this and it works fine
Suggested changes.
Create ServerSocket only once. If you have done it, you won't get "Address already in use" error
After creating Server Socket, you thread should be in while (true) loop to accept connection from client.
Once you create a client socket, pass that socket to thread.
Now Player is used to send communication from server to client socket. So You need one more class like PlayerClient which create a socket to Server IP and Port. Now PlayerClient should create one more thread to handle IO operations like you have done from server. In this case, creating a socket is not in while loop from client side. It create a socket to server once. Now you can run this PlayerClient program from multiple machines.
If you are just sending just primitive type, use DataOutputStream & DataInputStream instead of ObjectStreams
This code will become like this
try
{
address = InetAddress.getLocalHost();
serverSocket = new ServerSocket(6000);
System.out.println("server waits for players");
while ( true){
Socket socket = serverSocket.accept();
Player playerWhite = new Player(socket);
sendTestMessage(socket);// Move this method to Player thread and change the signature of this method accordingly to accept a socket
}
}
catch (IOException ex)
{
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
Player.java
Player(Socket socket) throws IOException
{
this.socket = socket;
start();
}
Have a look at this chat example for better understanding.
Yep it is.
It should work if you put it in a endlees loop like that:
try
{
while(true){
address = InetAddress.getLocalHost();
serverSocket = new ServerSocket(6000);
playerWhite = new Player();
System.out.println("server waits for players");
playerWhite.socket = serverSocket.accept();
playerWhite.start();
sendTestMessage(playerWhite);
}
}
catch (IOException ex)
{
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
But I would not recommend to put this in a thread. Instead I would put the connection of a new client in a thread, so multiple clients can connect to the server
(Disclaimer that some of this code will be similar to online tutorials)
I think I've made it so that my server can handle multiple requests at once using threads, but I'm not entirely sure. And on top of that I don't know how I would actually send multiple requests at once.
My goal is to run my client code multiple times in parallel to see what happens if multiple clients connect to the server at the same time.
Client code (in separate project package):
Client clientSocket = new Client(9990,"localhost");
Socket socket = new Socket(clientSocket.host,clientSocket.portNumber);
clientSocket.performTask(socket);
("performTask(socket)" sends data to the server to perform a task)
Server code (separate project package from client code):
Server server = new Server(9990);
int clientNumber = 0;
ServerSocket socket = new ServerSocket(server.portNumber);
try {
while (true) {
new ServerHandler(socket.accept(),clientNumber).go();
clientNumber++;
}
}
finally {
socket.close();
}
}
ServerHandler class (same project package as server code):
public class ServerHandler extends Thread {
private static Socket socket;
private static int clientNumber;
public ServerHandler(Socket socket, int clientNumber) {
ServerHandler.socket = socket;
ServerHandler.clientNumber = clientNumber;
}
public void go() {
while(true) {
try {
//do calculation, do server tasks, etc.
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
So when the client connects to the server, the server implements the ServerHandler class to do the necessary calculations: the idea in doing that was so that multiple clients could connect all at the same time.
So my question is then in two parts:
(1) Have I set up my programs to allow for multi-threading, or have I made a mistake somewhere along the way? (e.g. someone told me I needed to use "Runnable" somewhere to use multi-threading, and I notice I haven't)
(2) After fixing my code to allow for multi-threading, how would I actually use it to let me run my client code in parallel?
Ok for starters, your ServerHandler extends the Thread class. Therefore to make it run as a seperate thread, always invoke by calling the start() method. You are calling you custom go method which will make the ServerHandler execute in the same thread as your infinite while loop. So it should be something like this ServerHandler(socket.accept(),clientNumber).start(). Also it is always better to implement Runnable because java does not support multiple inheritance via the "extends" concept. Therefore in the future if your ServerHandler needs to actually extend a custom class, it wont be able to since it already extends the Thread class. Its better to implement interfaces since there is no limit as to how many you can implement.
Hence implementing the Runnable interface is a good design choice. You can run your client code in parallel by making the client into a threaded model. Here is one such example of multiple client sockets connecting to the server in parallel
Server Code
public class WebServer {
static int hitCount = 0;
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(7777, 10000);
while (true) {
Socket defaultSocket = serverSocket.accept();
new Thread(new ServerSlave(defaultSocket)).start();
System.out.println("Size is :" + hitCount);
}
}
}
class ServerSlave implements Runnable {
Socket clientSocket;
public ServerSlave(Socket socket) {
clientSocket = socket;
WebServer.hitCount++;
}
public void run() {
try {
DataInputStream inputStream = new DataInputStream(clientSocket.getInputStream());
DataOutputStream outputStream = new DataOutputStream(clientSocket.getOutputStream());
System.out.println(inputStream.readUTF());
outputStream.writeUTF("Thank you for contacting the web server");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Client Code :
public class Client {
static int excepCount=0;
public static void main(String[] args) throws Exception {
for (int i = 0; i < 100; i++) {
new Thread(new Worker("" + i)).start();
}
Thread.sleep(10000);
System.out.println( Client.excepCount);
}
}
class Worker implements Runnable {
String clientName;
public Worker(String name) {
clientName = name;
}
public void run() {
System.out.println("Process started for : " + clientName);
Socket socket = null;
try {
socket = new Socket("127.0.0.1", 7777);
DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
outputStream.writeUTF("Hello socket. Client number " + clientName + "here");
InputStream inFromServer = socket.getInputStream();
DataInputStream in =
new DataInputStream(inFromServer);
System.out.println("Server says " + in.readUTF());
System.out.println("Closing socket");
} catch (IOException e) {
Client.excepCount++;
e.printStackTrace();
}finally{
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
You should use multithreading .
You have to rename method to "run"/ and call that method using "start".Please change Server side code to
try {
while (true) {
new ServerHandler(socket.accept(),clientNumber).start();
clientNumber++;
}
}
finally {
socket.close();
}
and client side
public class ServerHandler extends Thread {
private static Socket socket;
private static int clientNumber;
public ServerHandler(Socket socket, int clientNumber) {
ServerHandler.socket = socket;
ServerHandler.clientNumber = clientNumber;
}
public void run() {
while(true) {
try {
//do calculation, do server tasks, etc.
}
} catch (IOException e) {
e.printStackTrace();
}
}
I'm using a server socket to accept clients on the main thread, when a thread is accepted,the clients socket is given to a handler which is started in a new thread to process communications. However, before I start running my server to access clients, it connects to a second server which it must list to and be able to respond to and pass on the messages it gets to it's clients.
Hopefully this image illustrate what I mean:
The small server must be continuously listening for input from the big server, and also able to output responses.
//Default constructor
private smallServer(){}
//method to initialise and start the server
public static void StartServer(int port) throws IOException {
smallServer ss = new smallServer();
ss.bs= new bigServerClient(ss);
Thread nsc_Thread = new Thread(ss.bsc);
bsc_Thread.start();
//accepts clients and starts new thread for them
ss.ServerRun(port);
}
private void ServerRun(int port) throws IOException {
ServerSocket server = new ServerSocket(port);
server.setSoTimeout(50);
while (run) {
Socket client = null;
try {
client = server.accept();
} catch (SocketTimeoutException e) {
}
if (client != null) {
ClientHandler handler = new ClientHandler(client, this);
Thread handleThread = new Thread(handler);
handleThread.start();
}
}
if (!run) {
synchronized (ClientHandler.handlers) {
for (ClientHandler handler : ClientHandler.handlers) {
handler.terminateHandler();
}
}
System.exit(0);
}
}
public void processBigServerCommand(String toProcess) {
System.out.println("RESEAVED: " + toProcess);
}
The big server client(on the small server) then does this:
public class bigServerClient implements Runnable {
private smalsServer ss;
private PrintWriter printer;
private BufferedReader reader;
private Socket socket;
public bigServerClient(smallServer _ss) throws IOException {
ss = _ss;
socket = new Socket("Localhost", 5000);
printer = new PrintWriter(socket.getOutputStream());
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
printer.flush();
SendBigServerMessage("Starting String");
}
private void SendBigServerMessage(String toSend) {
printer.print(toSend);
printer.flush();
}
#Override
public void run() {
try {
while (ss.state()) {
String inputLine;
while ((inputLine = reader.readLine()) != null) {
ss.processBigServerCommand(inputLine);
System.out.println(inputLine);
}
}
} catch (IOException e) {
} finally {
try {
socket.close();
} catch (IOException ex) {
}
}
}
}
From what's above, can anyone see why the big server client isn't responding to the big server when a message is sent? I'm guessing it's something to do with the main thread blocking the second thread, but I'm not sure... Any help would be greatly appreciated.
You lost me in your code...
Simplify it.
Your smallServer (see class names conventions) should have persistent connection to BigServer (effectively it is BigServer client) - you can implement it in your smallServer class, it should connect (once) and open I/O to BigServer (once) and close everything once the connection is terminated.
As your smallServer will handle multiple clients and pass their requests to BigServer there is no guarantee of the order of BigServer responses - you should do something to handle that (maybe pass UUID with requests?)
Simplify your smallServer and make sure that it runs...