Java Simple Client Server application - java

Im sorry I am coding 12 hours now and now I have a "brainlag".
I made a little Client Server programm.
Client:
public void send(String send) {
DataOutputStream out;
Socket client;
try {
client = new Socket("192.168.0.138", port);
out = new DataOutputStream(client.getOutputStream());
out.writeChars(send + '\n');
Thread.sleep(100L);
} catch (IOException ex) {
System.err.println("Can't connect to Server!");
} catch (InterruptedException ex) {
System.err.println("Cant sleep!");
}
}
Server:
public static void main(String[] args) throws IOException {
int port = 5000;
String cIn;
System.out.println("Running on Port 5000");
ServerSocket sock = new ServerSocket(port);
Socket client;
BufferedReader inFromClient;
while (true) {
client = sock.accept();
inFromClient = new BufferedReader(new InputStreamReader(client.getInputStream()));
cIn = inFromClient.readLine();
System.out.println("" + cln);
}
}
Now my question. How can i make it that my string (data) is sending in a loop to the server while I input a new data.
If a make a normal while loop, my string is sending permanently to the server. If i change my String it doesn't matter.
I would make it that if i change my String, that the new String is sending to the server.
I'm sorry for my bad english. I hope you will understand.

how about sending the data with a new thread whichs sends the data in a loop. when you input some new data interupt the old thread and start a new one and so on?

I think you need to add a bufferedReader close at the end of the while loop.
while (true) {
client = sock.accept();
inFromClient = new BufferedReader(new InputStreamReader(client.getInputStream()));
cIn = inFromClient.readLine();
System.out.println("" + cln);
inFromClient.close() //add this
}

If I resume:
- you need a console app (or window/awt/swing ...) or main client app which take a String, and sometimes change this String.
- this String must be sent by your function "send", continuously, with the last String
I propose you:
1 - to fix the loop (1 sec, 2, sec, x seconds ?)
2 - to use a share variable (in critical section, or synchronized), your main client app writes it, and changes it when you want, and your "send" function read it every x seconds and sends it.
Your client could look like that:
// SHARED VARIABLE
static String warning="";
final static Object warning_sync=new Object();
// Alert function
class Thread_alert extends Thread
{
// YOUR CODE
public void send(String send) {
DataOutputStream out;
Socket client;
int port=80;
try {
client = new Socket("192.168.0.138", port);
out = new DataOutputStream(client.getOutputStream());
out.writeChars(send + '\n');
Thread.sleep(100L);
} catch (IOException ex) {
System.err.println("Can't connect to Server!");
} catch (InterruptedException ex) {
System.err.println("Cant sleep!");
}
}
public Thread_alert()
{
super();
}
public void run()
{
while (true)
{
// WHAT YOU HAVE TO DO
synchronized(warning_sync)
{
System.err.println("WARN: "+warning);
send(warning);
}
// Sleep 5 seconds
try {
Thread.sleep(5000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
// while (true)
}
// public void run()
}
// class Thread_alert
public void console_client ()
{
// START THE THREAD
Thread_alert lethread=new Thread_alert();
lethread.start();
// INPUT LOOP
Scanner s = new Scanner(System.in);
String line;
while ((line=s.nextLine())!=null)
{
System.out.println("STRING:'"+line+"'");
// Fix the warning
synchronized(warning_sync)
{
warning=line;
}
// bonus
// IF STOP: STOP
if (warning.equals("STOP"))
{
lethread.stop();
break;
}
}
// while ((line=s.nextLine())!=null)
// safe
s.close();
}

Related

Java - Getting error "Socket is closed" when my Client class connects on my Server class

I made two classes in Java named Server.java and Client.java. The Server is listening to a port and is waiting for a Client to connect (using sockets). When the client connects he can type a pair of numbers separated by "space" and if that pair exists in my edge_list.txt file the Server returns "1" to the client, if not it returns "0". After I completed my initial project I wanted to also use Threads so that it can handle multiple users at once, but when the Client connects I get -> java.net.SocketException: Socket is closed.
I reviewed my code and try using flush() instead of close(). Also, I thought I was closing the socket before the user can read the file, but it didn't seem that was the case. Below I will have the Server.java code block and not the Client.java, cause it doesn't seem to be the problem.
Server.java
import java.io.*;
import java.net.*;
import java.util.*;
public class Server {
private static final int PORT = 9999;
public static void main(String[] args) {
try (ServerSocket serverSocket = new ServerSocket(PORT)) {
System.out.println("Server is listening on port " + PORT);
while (true) {
try (Socket socket = serverSocket.accept()) {
System.out.println("Client connected: " + socket);
new ClientHandler(socket).start();
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static class ClientHandler extends Thread {
private Socket socket;
ClientHandler(Socket socket){
this.socket = socket;
}
#Override
public void run() {
try {
//Creating Sockets and Streams
InputStream input = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
OutputStream output = socket.getOutputStream();
PrintWriter writer = new PrintWriter(new OutputStreamWriter(output));
while (socket.isConnected() && !socket.isClosed()) {
//Reading what the Client types
String request = reader.readLine();
//Split the values with "space" and store them in an array,
//then parse those values to two integers
String[] values = request.split(" ");
int A = Integer.parseInt(values[0]);
int B = Integer.parseInt(values[1]);
//Check if the pair in the file exists using checkPairInFile() method
boolean exists = checkPairInFile(A, B);
//if it does print 1 else 0
writer.println(exists ? "1" : "0");
//Flush the output to send the response back to the client
writer.flush();
}
//Print the disconnected user
System.out.println("Client disconnected: " + socket);
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static boolean checkPairInFile(int A, int B) {
try (Scanner scanner = new Scanner(new File("edge_list.txt"))) {
//Scanning the file lines
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
//Split the values with "space"
String[] values = line.split(" ");
//Parse the values from String -> Int
int a = Integer.parseInt(values[0]);
int b = Integer.parseInt(values[1]);
//if both exist return true
if (A == a && B == b) {
return true;
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return false;
}
}
P.S. Thanks in advance for your help, in case this is problem with my Client.java file I will update the post.
This part:
try (Socket socket = serverSocket.accept()) {
System.out.println("Client connected: " + socket);
new ClientHandler(socket).start();
}
accepts a socket, then prints a message, then starts a new thread, then closes the socket. At some point later the new thread finishes starting up and tries to use the socket and realizes it was already closed.
try (...) {...} (officially called try-with-resources) always closes the things when it gets to the }. That's the point of it. If you don't want to close the socket at the } then you shouldn't use this type of statement.

Where to put the line "serverSocket.accept();" in a multithreaded java program

I am trying to create a program where the server and client can send and receive messages to/from each other at the same time (the same way two people with phones can text each other)
There are three files (the main function file, the server file, the client file) I want to only focus on server and main file for now.
The problem with the server file is that there are two separate threads where each thread has its own separate "run" function so I am wondering where I should put the "socket.accept()" line in order to make both of them work (perhaps before, globally somehow?)
The command line arguments to run the server are
java DirectMessengerCombined -l 3000
if "-l" is not present, then it will run as a client
The flow of the Server file I think would go something like this (psuedo-code comments) (correct me if I'm wrong)
//Server listens for connections
//then accepts the connection from client
//Recieving msesages:
//function recieves messages, create and run a functon that recieves messages
//read from the socket until the other side closes
//display the recieved message
//Sending: Standard input begins
//create and run a functon that sends messages
//write using standard input as long as the user doesn't close it, in a loop
//user close standard input to end the program
According to this flow, would it be possible to accept a connection outside the first run method from the thread? Perhaps in the constructor?
Server Code:
import java.io.*;
import java.net.*;
import java.util.*;
import javax.imageio.IIOException;
public class DirectMessengerServer
{
private String[] serverArgs;
private static Socket socket;
public boolean keepRunning = true;
public DirectMessengerServer(String[] args) throws IOException
{
// should serverSocket.accept() go here???
// set the instance variable
this.serverArgs = args;
int port_number1 = Integer.valueOf(serverArgs[1]);
ServerSocket serverSocket = new ServerSocket(port_number1);
socket = serverSocket.accept();
}
public String[] ServerRun(String[] args)
{
serverArgs = args;
serverArgs = Arrays.copyOf(args, args.length);
return serverArgs;
}
// should serverSocket.accept() go here???
Thread ServerRecieve = new Thread();
//If i put serverSocket.accept() in both the run methods, won't that cause an "Address already in use error"?
//run method of ServerRecieve
public void run(String args[])
{
System.out.println("Server recieve thread is now running");
try
{
while(keepRunning)
{
//Reading the message from the client
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String MessageFromClient = br.readLine();
System.out.println("Message received from client: "+ MessageFromClient);
}
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
try
{
socket.close();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Thread ServerSend = new Thread ();
//Run method of ServerSend
public void run()
{
while(keepRunning)
{
System.out.println("Server sending thread is now running");
try
{
//Send the message to the server
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
//creating message to send from standard input
String newmessage = "";
try
{
// input the message from standard input
BufferedReader input= new BufferedReader(
new InputStreamReader(System.in));
String line = "";
line= input.readLine();
newmessage += line + " ";
}
catch ( Exception e )
{
System.out.println( e.getMessage() );
}
String sendMessage = newmessage;
bw.write(sendMessage + "\n");
bw.flush();
System.out.println("Message sent to client: "+sendMessage);
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
}
}
}
}
Code of main function file:
import java.io.IOException;
public class DirectMessengerCombined
{
public static void main(String[] args) throws IOException
{
DirectMessengerClient Client1 = new DirectMessengerClient();
// Thread t1 = new Thread(Client1);
DirectMessengerServer Server1 = new DirectMessengerServer(args);
//DirectMessengerServer Server1 = new DirectMessengerServer(args[1], null, 0);
for (int i = 0; i < args.length; i++)
{
if(!args[0].equals("-l"))
{
Client1.ClientRun(args);
}
switch (args[0].charAt(0))
{
case '-':
if(args[0].equals("-l"))
{
Server1.ServerRun(args);
}
}
i=args.length + 20;
}
}
}
My question is: where is the right place to accept the connections in the code so that both run methods will be able to work as if they both were connected?
Normally you will put it inside a loop in its own thread, and you will start a new thread per accepted connection.

Server-Client what is wrong here?

So this is the first Server-Client I am trying to 'setup' but it does not work as I want it to. Here is What I want:
The Client to do: (see comments in the code for the Client)
A 'user input' should be read by the Client
Send the 'user input' to the server
receive back something from the server
The server to do: (See the comments in the code for Server)
receive the 'user input' that read by the client
Do something with the 'user input'
Send what was done in (2), back to the client.
It is not working the only right thing it is doing is that it receives the input from the 'user', that is it:
public class Cli {
BufferedReader in;
PrintWriter out;
Socket s;
public Cli(int port){
try {
s = new Socket("127.0.0.1", port);
out = new PrintWriter(s.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader
(s.getInputStream()));
} catch (UnknownHostException e) {
System.out.print("fel");
} catch (IOException e) {
System.out.print("fel");
}
}
public void startaClient(){
BufferedReader stdIn = new BufferedReader (new InputStreamReader(System.in));
try {
while(true){
String userInput = stdIn.readLine();// get the user input (1)
System.out.print("from user: " + userInput);
out.write(userInput); // sends to server (2)
System.out.println(in.readLine()); // receive from server(3)
}
} catch (Exception e){
System.out.println("fel1");
}
}
public static void main(String[] args){
Cli c=new Cli(4002);
c.startaClient();
}
Here is the code for the Server:
public class Ser {
ServerSocket s;
public Ser()throws Exception{
s = new ServerSocket(4002);
}
public void startaServern()throws Exception {
while (true) {
Socket socket = s.accept(); //waits for new clients, acceptera inkommande förfrågan
Trad t = new Trad(socket);
t.start();
}
}
public static void main(String[] args)throws Exception{
Ser b = new Ser();
b.startaServern();
}
}
public class Trad extends Thread {
Socket socket;
BufferedReader in;
PrintWriter out;
public Trad(Socket s){
socket=s;
try{
in = new BufferedReader(new InputStreamReader(socket.getInputStream())); //
out=new PrintWriter(socket.getOutputStream(),true);
}catch(Exception e){System.out.println("fel");}
}
public void run(){
while(true){
try{
String theInput = in.readLine(); //read, receive message from client (1)
String res = theInput+"blabla"; // do something with the message from the client (2)
out.write(res); // send it back to the client (3)
} catch(Exception e) {
System.out.println("fel1");
}
}
}
}
When you do readLine() it will read a line i.e. until it reaches a new line.
Unless you send a new line it will wait forever. I suggest you send a newline so the reader knows the line has ended.
Since you are using a PrintWriter the simplest solution is to use
out.println(res);
instead of out.write(res);

How to make two seperate clients share the same data from the server?

I have this server and client application that counts how many times a button has been clicked. Some other members here were kind enough to solve my previous issue with it, and now I have another.
When I start up the server, and a client connects, and the client clicks the button, the counter on the server side goes up. However, when a second client connects to the server, the counter resets to 0. I am thinking that the server creates a seperate instance of the counter for some reason.
Here is the (updated) server sided code:
public class Server {
public static void main(String[] args) throws Exception {
Socket socket = null; //create a new socket
ServerSocket listener = new ServerSocket(9898);
System.out.println("The server is running!");
try {
while (true) {
new ClickServer(listener.accept()).start();
}
} finally {
listener.close();
}
}
/**
* A private thread to handle clicking requests
*/
private static class ClickServer extends Thread {
private Socket socket;
AtomicInteger totalBets = new AtomicInteger(0);
public void incrementTotalBets() {
totalBets.incrementAndGet();
}
public int getTotalBets() {
return totalBets.get();
}
public ClickServer(Socket socket) {
this.socket = socket;
log("New connection with client at " + socket);
}
public void run() {
try {
while (true) {
socket.setTcpNoDelay(true);
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String input = br.readLine();
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
if(input.equals("increment")) {
bw.write(String.valueOf(totalBets.incrementAndGet()));
bw.newLine();
bw.flush();
System.out.println("Total Bets: " + getTotalBets());
}
}
} catch (IOException e) {
log("Error handling client\n" + e);
} finally {
try {
socket.close();
} catch (IOException e) {
log("Error closing socket");
}
log("Connection with client closed");
}
}
private void log(String message) {
System.out.println(message);
}
}
}
The totalBets integer is the counter. When multiple client join the server, and click the button, it should increment the counter and send it back based on what the counter already is. It shouldn't reset for every new client.
Here is the relevant client-sided code:
public void actionPerformed(ActionEvent arg0) {
try {
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
String target = "";
bw.write("increment" + "\n");
bw.flush();
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String id = br.readLine();
System.out.println("bet added: " + id);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
I'm not sure why a new instance of the Server is being created every time a new client connects. I did some debugging, and the server knows there is more than one client connected to the server at the same port.
Any help?
Thank you.
NOTE: the ClickServer class is nested inside the Server class. It just doesn't look that way in the code box.
You'd need a shared counter that's thread safe. I'd go for
public static AtomicInteger totalBets = new AtomicInteger (0);
You'd have to change getter and setter some but this should share value between Clients. Or trash those methods and simply do
if(input.equals("increment")) {
bw.write(String.valueOf(totalBets.incrementAndGet ()));
Try changing :
public int totalBets = 0;
to:
public static int totalBets = 0;

Read/write in simple client-server app in Java

I'm new with Java and I'm trying to learn threads and socket. So decide to make simple client-server application following official java tutorial. My idea is simple - server wait for connection, if appears, it makes new thread with new socket, input and output. Client side -> make connection; new thread with socket, input, output and stdIn (to read line and after that send it to the server). But something is wrong (don't have any idea why) with my code. The connection is established, there's no exceptions. Could someone explain why doesn't work and how to fix it? Also could you have any suggestions about the code (probably it's not with best practices and things like that):
Client side:
public class Client {
private BufferedReader reader;
private Socket sock;
private PrintWriter writer;
public static void main(String[] args) {
Client client = new Client();
client.go();
}
public void go() {
setUpNetworking();
}
private void setUpNetworking() {
try{
sock = new Socket("127.0.0.1", 5000);
System.out.println("Network established");
ServerThread serverThread= new ServerThread(sock);
serverThread.start();
System.out.println("Type your message: ");
} catch (IOException e) {
System.out.println("Problem with establishing the network: " + e);
}
}
class ServerThread extends Thread {
Socket socket;
PrintWriter out;
BufferedReader in;
BufferedReader stdIn;
ServerThread(Socket socket) {
this.socket = socket;
try{
out = new PrintWriter(socket.getOutputStream());
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
stdIn = new BufferedReader(new InputStreamReader(System.in));
}catch (IOException e) {
System.out.println("Problem with trying to read/write to server: " + e);
}
}
#Override
public void run() {
String fromServer;
String fromClient;
while(true){
try{
if((fromServer = in.readLine()) != null) System.out.println(" " + fromServer);
else if((fromClient = stdIn.readLine()) != null) out.println(fromClient);
}catch(Exception e) {
System.out.println("msg exception: " + e);
}
}
}
}
}
Server side:
public class Server {
//Run server until keepGoing = false
private boolean keepGoing = true;
public static void main(String[] args) {
Server server = new Server();
server.go();
}
public void go() {
try {
ServerSocket serverSocket = new ServerSocket(5000);
while(keepGoing) {
Socket clientSocket = serverSocket.accept();
ClientThread t = new ClientThread(clientSocket);
t.start();
}
} catch (IOException e) {
System.out.println("Problem with socket/network: " + e);
}
}
class ClientThread extends Thread {
Socket clientSocket;
PrintWriter out;
BufferedReader in;
ClientThread(Socket clientSocket) {
this.clientSocket = clientSocket;
try{
out = new PrintWriter(clientSocket.getOutputStream());
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
} catch (IOException e) {
System.out.println("Problem with creating in/out: " + e);
}
}
#Override
public void run() {
String message;
while(keepGoing) {
try{
message = in.readLine();
out.println(message);
System.out.println(message);
} catch (IOException e){
System.out.println("Exception while try to read line: " + e);
}
}
}
}
}
PS I've changed a bit the code - instead of made ClientThread Class, I made new runnable class and pass that variable to thread class. Inspired by this question: "implements Runnable" vs. "extends Thread".
I think the problem is that both server and client are waiting for any input. Server:
message = in.readLine();
Client:
if((fromServer = in.readLine()) != null)
System.out.println(" " + fromServer);
else if((fromClient = stdIn.readLine()) != null)
out.println(fromClient);
But the client code already blocks on the fromServer = in.readLine() part, so it never gets to read from standard in, and thus nothing will be sent out to the server.
You could move your attempt to read from standard in to the setUpNetworking method, right after the System.out.println("Type your message: ");. Build a loop there which you exit if the user types "exit" or "quit" or something like that:
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
String read = "";
do {
read = stdIn.readLine();
System.out.println("Read from stdin: " + read);
serverThread.send(read);
}
while (!read.equals("exit"));
The ServerThread.send() method is simple:
void send(String string) {
System.out.println("Sending to server: " + string);
out.println(string);
}
However, to make it work, you either have to flush the stream manually after writing to out, or use the following constructor:
out = new PrintWriter(socket.getOutputStream(), true);
See the PrintWriter's JavaDoc: True means auto-flush on newline.
I tested this setup and it worked for me. I was able to send something from the client to the server.
However, this is only the first step. I would implement both reading and writing as separate threads, for both client and server. And there is no graceful shutdown of sockets implemenented yet. A more complete yet simple example can be found on Oracle.

Categories

Resources