Why the server stops running when I close the Client? - java

I am writing my first Client-Server program in Java using Sockets. I am using Eclipse as the IDE. When I am testing the communication between both programs (server and client) I run first the server using the command prompt and then I run the client in Eclipse. Everything works fine, I can read from and write to the socket, however, when I close the client program in Eclipse, the server program closes too. Why is this happening? The server is supposed to be running by itself in the command prompt, it is not dependent on a client.
Also I would like to know if there is any possibility I can run both programs in Eclipse instead of opening the server in the command prompt first.
Here is my code for both programs:
Server:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerPrg {
public static void main(String[] args) {
System.out.println("Server is running.....");
try {
ServerSocket socketSer = new ServerSocket(4444);
Socket clientSocket = socketSer.accept();
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = (new BufferedReader (new InputStreamReader(clientSocket.getInputStream())));
BufferedReader stdIn = (new BufferedReader (new InputStreamReader(System.in)));
System.out.println("Client: " + in.readLine());
String input ;
while((input = stdIn.readLine()) != null)
{ out.println(input);
System.out.println("Client: " + in.readLine());
}
}
catch (Exception e) {System.out.println("CAN'T CREATE SERVERSOCKET. PROBABLY THE PORT IS BEING USED " + e);}
} //end main
} //end public class
Client:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class ClientPrg {
public static void main(String[] args) {
int portNumber = 4444;
try {
Socket clientSocket = new Socket("127.0.0.1", portNumber);
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
String input;
while ((input = stdIn.readLine()) != null)
{
out.println(input);
System.out.println("Server: " + in.readLine());
}
} catch(Exception e)
{
System.out.println(e);
System.out.println("CAN'T CONNECT TO THE SERVER");
}
} //end main
} // end public class

Your server lacks a loop around accepting client sockets.
This means that after your client socket is accepted, it will exit because there is no flow control element that will have it attempt to accept a second client socket.
A simple loop around accepting client sockets is probably not exactly what you want. That is because there will be only one Thread in the solution, which means that while a client is being handled, other clients won't be able to be accepted.
There are many ways to handle the situation above. One of the simplest is to create a thread for every accepted client to handle the client's communications. While this is initially simple, it does not scale very well. With a large number of clients, the thread count will rise, and most computers can handle many more network connections than threads.
The scope of talking about services that scale well is far to big to address here; but, after you get familiar with one thread per client processing, start looking at Java NIO.

Related

BungeeCord not reachable after enabling ServerSocket

I'm working on an web based API for a BungeeCord Server but after opening the ServerSocket on Port 8082 the BungeeCord on Port 25565 isn't available furthermore.
This class is opening the ServerSocket:
package de.pardrox.bungeeapi;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class HTTP {
static router router = new router();
public static void main(int args) {
try {
int port = args;
#SuppressWarnings("resource")
ServerSocket apiweb = new ServerSocket(port);
for (;;) {
Socket client = apiweb.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out = new PrintWriter(client.getOutputStream());
out.print("HTTP/1.1 200 \r\n");
out.print("Content-Type: text/plain\r\n");
out.print("Connection: close\r\n");
out.print("\r\n");
String line;
InetAddress ip_client = client.getInetAddress();
main.syslog("Request of client "+ip_client.toString());
while ((line = in.readLine()) != null) {
if (line.length() == 0)
break;
if(line.toLowerCase().contains("GET".toLowerCase()))
{
String url = line.replace("GET ", "").replace(" HTTP/1.1", "");
out.print(router.get(url));
}
}
out.close();
in.close();
client.close();
}
}
catch (Exception e) {
System.err.println(e);
System.err.println("Call HTTP(<port>)");
}
}
}
Does anyone have an idea why opening the ServerSocket seems to close the Socket of the Gameserver? Eclipse doesn't find any error and the gameserver itself seems to run fine. The API is reachable also without any trouble.
For completeness:
I've startet the socket class with HTTP.main(8082);
I think there's a mistake at for (;;).
This will create an infinite loop that will run for ever....
Maybe this will cause the Main Thread of BungeeCord server to stop responding.
Try removing the for (;;) and using this code below instead of just running the code in the Default BungeeCord Thread. Since BungeeCord doesn't allows you to create custom Threads, the only way to do this is using the Scheduler and running a Runnable asynchronous.
ProxyServer.getInstance().getScheduler().runAsync(yourPluginHere, new Runnable() {
#Override
public void run() {
// Put your code here
}
});

Android Client/Server socket confusion concept on moving forward

I'm trying to learn about client/server and sockets right now but I'm confused on the bigger scope of things. I followed a tutorial that has a client as an android app and the server is a java application. I run both of them on eclipse fine.
My question now is how do I make this global? So I'll take my server code written in java, export it to a text called server.java, and then upload it to my personal site? And then when I start my client android app, I'll make a call to say http://blah.com/server.java to start my server, right? Then my server will begin listening on that port and my client can connect to it?
Server:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class SimpleTextServer {
private static ServerSocket serverSocket;
private static Socket clientSocket;
private static InputStreamReader inputStreamReader;
private static BufferedReader bufferedReader;
private static String message;
public static void main(String[] args) {
try {
serverSocket = new ServerSocket(4444); // Server socket
} catch (IOException e) {
System.out.println("Could not listen on port: 4444");
}
System.out.println("Server started. Listening to the port 4444");
while (true) {
try {
clientSocket = serverSocket.accept(); // accept the client connection
inputStreamReader = new InputStreamReader(clientSocket.getInputStream());
bufferedReader = new BufferedReader(inputStreamReader); // get the client message
message = bufferedReader.readLine();
System.out.println(message);
//will later add an output stream to write back to android
inputStreamReader.close();
clientSocket.close();
} catch (IOException ex) {
System.out.println("Problem in message reading");
}
}
}
}

Server Socket won't accept() local application handshake in Java

I am trying to connect a client application to my code through port 8000 on my pc offline. I am using the ServerSocket library to connect using the below code. The client's application sends XML messages across the port and I need to connect, interpret and respond. (Please bear in mind that I haven't coded interpret/respond yet when reading the below).
Every time I try to send a message from the client application (when running the debug feature in eclipse), the code gets to the serverSocket.accept() method which should be the 'handshake' between client and server and can't go any further. I am unable to change the client application obviously so need to figure out why it's not accepting the connection.
package connect;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class PortListener2 {
public static void main(String[] args){
System.out.println("> Start");
int portNumber = 8000;
try (
ServerSocket serverSocket =
new ServerSocket(portNumber);
Socket clientSocket = serverSocket.accept();
PrintWriter out =
new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
) {
String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println("Received: "+inputLine);
out.println(inputLine);
if (inputLine.equals("exit")){
break;
}
}
} catch (Exception e) {
System.out.println("Exception caught when trying to listen on port "
+ portNumber + " or listening for a connection");
System.out.println(e.getMessage());
e.printStackTrace();
} finally {
System.out.println("Disconnected");
}
}
}

Handle streams with multiple clients?

basically what i want to do is develop a chat program(something between an instant messenger and IRC) to improve my java skills.
But I ran into 1 big problem so far: I have no idea how to set up streams properly if there is more than one client. 1:1 chat between the client and the server works easily, but I just don't know what todo so more than 1 client can be with the server in the same chat.
This is what I got, but I doubt its going to be very helpful, since it is just 1 permanent stream to and from the server.
private void connect() throws IOException {
showMessage("Trying to connect \n");
connection = new Socket(InetAddress.getByName(serverIP),27499);
showMessage("connected to "+connection.getInetAddress().getHostName());
}
private void streams() throws IOException{
output = new ObjectOutputStream(connection.getOutputStream());
output.flush();
input = new ObjectInputStream(connection.getInputStream());
showMessage("\n streams working");
}
To read from multiple streams in one program, you're going to have to use multithreading. Because reading from streams is synchronous, you'll need to read from one stream for each thread. See the java tutorial on threads for more info on multithreading.
I've done this several times with ServerSocket(int port) and Socket ServerSocket.accept(). This can be pretty simple by having it listen to the one port you want your chat server client listening on. The main thread will block waiting for the next client to connect, then return the Socket object to that specific client. Usually you'll want to put them in a list to generically handle n-number of clients.
And, yes, you will probably want to make sure each Socket is in a different thread, but that's entirely up to you as the programmer.
Remember, there is no need to re-direct to another port on the server, by virtue of the client using a different source port, the unique 5-tuple (SrcIP, SrcPort, DstIP, DstPort, TCP/UDP/other IP protocol) will allow the one server port to be re-used. Hence why we all use stackoverflow.com port 80.
Happy Coding.
Made something like that a few months back. basically I used a separate ServerSocket and Thread per client server side. When client connects you register that port's input and output streams to a fixed pool and block until input is sent. then you copy the input to each of the other clients and send. here is a basic program run from command line:
Server code:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class ChatServer {
static int PORT_NUMBER = 2012;
public static void main(String[] args) throws IOException {
while (true) {
try (ServerSocket ss = new ServerSocket(PORT_NUMBER)) {
System.out.println("Server waiting #" + ss.getInetAddress());
Socket s = ss.accept();
System.out.println("connection from:" + s.getInetAddress());
new Worker(s).start();
}
}
}
static class Worker extends Thread {
final static ArrayList<PrintStream> os = new ArrayList(10);
Socket clientSocket;
BufferedReader fromClient;
public Worker(Socket clientSocket) throws IOException {
this.clientSocket = clientSocket;
PrintStream toClient=new PrintStream(new BufferedOutputStream(this.clientSocket.getOutputStream()));
toClient.println("connected to server");
os.add(toClient);
fromClient = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream()));
}
#Override
public void run() {
while (true) {
try {
String message = fromClient.readLine();
synchronized (os) {
for (PrintStream toClient : os) {
toClient.println(message);
toClient.flush();
}
}
} catch (IOException ex) {
//user discnnected
try {
clientSocket.close();
} catch (IOException ex1) {
}
}
}
}
}
}
Client code:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
public class Client {
public static void main(String[] args) throws IOException {
final BufferedReader fromUser = new BufferedReader(new InputStreamReader(System.in));
PrintStream toUser = System.out;
BufferedReader fromServer;
final PrintStream toServer;
Socket s = null;
System.out.println("Server IP Address?");
String host;
String port = "";
host = fromUser.readLine();
System.out.println("Server Port Number?");
port = fromUser.readLine();
s = new Socket(host, Integer.valueOf(port));
int read;
char[] buffer = new char[1024];
fromServer = new BufferedReader(new InputStreamReader(s.getInputStream()));
toServer = new PrintStream(s.getOutputStream());
new Thread() {
#Override
public void run() {
while (true) {
try {
toServer.println(">>>" + fromUser.readLine());
toServer.flush();
} catch (IOException ex) {
System.err.println(ex);
}
}
}
}.start();
while (true) {
while ((read = fromServer.read(buffer)) != -1) {
toUser.print(String.valueOf(buffer, 0, read));
}
toUser.flush();
}
}
}

Java: how to detect in the server, whether a client socket has been closed?

Environment: Java 6, windows xp
I am trying to write a client-server TCP socket application. Need to detect on the server, when the client has closed the socket. All the information on the Internet, says that the server will throw a socket exception when its not able to write.
However, when I run the code (see below), I see that the server gets the exception only when the client doesn't read anything from the stream. When the client reads from the input stream, no exception is thrown on the server.
can someone please tell me the right way to detect a client side socket close (and also explain the behavior exhibited by the code below)?
Code:
package com.connection;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.ServerSocket;
import java.net.Socket;
public class Test implements Runnable{
ServerSocket ss = null;
public Test() throws Exception{
ss = new ServerSocket(9999);
}
public void run(){
try{
Socket s = ss.accept();
Writer w = new OutputStreamWriter(s.getOutputStream());
w.write("Hello\n");
w.flush();
System.out.println("Server: wrote string 1");
System.out.println("Server: sleeping...");
Thread.sleep(5000);
System.out.println("Server: woke up");
w.write("Hello\n");
w.flush();
System.out.println("Server: wrote string 2");
}catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception{
Thread server = new Thread(new Test());
server.start();
Thread client = new Thread(new TestClient());
client.start();
}
}
class TestClient implements Runnable{
public void run() {
try {
Socket s = new Socket("localhost", 9999);
// Comment out the below 4 lines to see the write exception on server
BufferedReader r = new BufferedReader(new InputStreamReader(s.getInputStream()));
System.out.println("Client: reading input...");
String str = r.readLine();
System.out.println(str);
// Comment the *above* 4 lines to see exception on server
Thread.sleep(1000);
System.out.println("Client: woke up");
s.close();
System.out.println("Client: socket closed");
}catch(Exception e){
e.printStackTrace();
}
}
}

Categories