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.
Related
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.
I am trying to create program with three files (main function file, server file, client file)
I want to focus only on the main and server file for now.
The program will run as a server if the following command line arguments are present:
java DirectMessengerCombined -l 3000
If "-l" is not present, it will run as a client
In the server file there are two separate run methods for two separate threads (one for receiving messages, one for sending messages) (not sure how to resolve the fact that the method name "run" appears twice in the program)
The main function file is the one that contains the (String args[]) command line arguments
I am trying to access args[] in both of the the server thread run methods.
Code of main function file:
import java.io.IOException;
public class DirectMessengerCombined
{
public static void main(String[] args) throws IOException
{
DirectMessengerClient Client1 = new DirectMessengerClient();
DirectMessengerServer Server1 = new DirectMessengerServer();
//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;
}
}
}
As you can see, the "args" is passed inside the line of code that says:
Server1.ServerRun(args);
In the following code, the method at the beginning named "ServerRun" has access to the real command line arguments (from the passed in parameter "String[] args"). I want to be able to use and/or access the "String args[]" from the ServerRun method parameters to be used inside the separate run methods to get the port number.
Code of Server:
import java.io.*;
import java.net.*;
import java.util.*;
import javax.imageio.IIOException;
public class DirectMessengerServer
{
private static Socket socket;
boolean KeepRunning = true;
void ServerRun(String[] args)
{
//How do I get the String[] args in this method be able to access it in the run methods?
}
Thread ServerRecieve = new Thread();
Thread ServerSend = new Thread ();
//Run method of ServerSend
public void run()
{
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
{
}
// }
}
//run method of ServerRecieve
public void run(String args[])
{
System.out.println("Server recieve thread is now running");
try
{
System.out.println("Try block begins..");
int port_number1= Integer.valueOf(args[1]);
System.out.println("Port number is: " + port_number1);
ServerSocket serverSocket = new ServerSocket(port_number1);
//SocketAddress addr = new InetSocketAddress(address, port_number1);
System.out.println( "Listening for connections on port: " + ( port_number1 ) );
while(KeepRunning)
{
//Reading the message from the client
socket = serverSocket.accept();
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();
}
}
}
}
My question is, how can I get the string[] args from inside the ServerRun parameters, store it somewhere to be used in the separate run methods later in the program?
In answer to the specific question of how to access the args in another method of the class, the following will work.
I would suggest moving the args parameter to the constructor rather than via method call, as shown here. Of course a method can set an instance variable, but then the instance variable cannot be final. As the variable should not need to change references, final is the most appropriate approach, I believe.
public class DirectMessengerServer
{
private final String[] serverArgs; // <-- added variable
private static Socket socket;
boolean keeyRunning = true;
public DirectMessengerServer(String[] args)
{
// set the instance variable
this.serverArgs = args;
}
public void run()
{
// access the serverArgs instance variable
System.out.println(serverArgs[0]);
}
//
// from the dirver program
//
public static void main(String[] args)
{
// after verifying the args as desired
DirectMessengerServer server1 = new DirectMessengerServer(args);
}
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();
}
I've written some serverside socket handling code and I'm concerned that potentially my packets are not always making it back to the client. I am logging all my events and in my log files it says I am sending the information. But the client is also logging events and in their logs they say they do not receive anything.
My code to send the data is as follows:
public void write(Packet packet) {
String data = packet.serialize();
log("Send=[" + data + "]", "Write"); // log to file
try {
_writer.write(data);
_writer.flush();
} catch (Exception ex) {
log(ex, "write");
}
}
Each socket is created on a new thread and I create my writers and readers immediately like so (in the public run method):
// _sockt is a Java Socket object
_writer = new BufferedWriter(new OutputStreamWriter(_socket
.getOutputStream()));
_reader = new SocketReader(_socket);
SocketReader is just a wrapper class I created for listening for responses and has a public read method like so:
public String read() throws IOException, SocketTimeoutException {
_socket.setSoTimeout(_timeOut);
if(_reader == null)
_reader = new BufferedReader(new InputStreamReader(_socket.getInputStream()));
// read from the stream
return new PacketDataInputStream(_reader).read();
}
The PacketDataInputStream wrapper class:
BufferedReader _reader = null;
public PacketDataInputStream(BufferedReader reader)
{
_reader = reader;
}
public String read() throws IOException, SocketException {
StringBuilder builder = new StringBuilder();
int c = 0;
while((c = _reader.read()) != -1)
{
char ch = (char)c;
builder.append(ch);
if(ch == PacketConstants.ETX)
break;
}
if(builder.length() > 0)
return builder.toString();
else
return null;
}
The way I'm creating the actual socket listener objects is pretty standard I think:
InetAddress address = InetAddress.getByName(IP);
server = new ServerSocket( port, 0, address);
// My own manager class to handle all the sockets connected
WebSocketManager manager = new WebSocketManager(this);
Socket connection = null;
while(bContinue)
{
connection = server.accept();
if(bContinue) {
// assign the socket to a new thread and start
// that thread
manager.newSocket(connection);
} else {
connection.close();
}
}
Is is possible that I'm using the wrong objects for sending the data back.
Should I even be using a bufferedwriter and reader? I had thought that these were the best way to go but now I'm not so sure.
It's important to note that this does not happen all the time, just sporadically. It could be the clients code having bugs but I need to make sure that I'm doing it correctly before going back to them.
This code is run on a Linux Ubuntu server. Logging occurs to a text file, nothing special there. My log files show the Send="" data going back to the client and no exception so it appears as if the .write and .flush() worked? Socket connections are persistant and only closed by the client and or network issues.
UPDATE ----- Client Side code -------:
I did manage to get some of the client side code for how they are handling the send and receiving of data (just in case it's more obvious on their end). The client is actually connecting to this server via an Android device (if that helps).
Creation of socket
static final int BUFFER_SIZE = 20000; // Maximum packet size
java.net.InetAddress server = java.net.InetAddress.getByName(url);
socket = new Socket(server, port);
// Set socket options:
socket.setReceiveBufferSize(BUFFER_SIZE);
socket.setSendBufferSize(BUFFER_SIZE);
socket.setKeepAlive(true);
socket.setTcpNoDelay(true);
Sending:
try {
// Send the packet:
OutputStream stream = socket.getOutputStream();
stream.write(p.getByteArray ());
stream.flush();
// Update the time:
lastPacketSendTime = new Date ();
} catch (IOException e) {
setError("Error sending packet (" + e.getMessage() + ")", ERROR_IO);
return false;
}
Receiving:
socket.setSoTimeout(timeout);
// Get the reader:
inputStream = socket.getInputStream();
while (true) {
// Get the next character:
int value = inputStream.read();
// Check for -1, indicating that the socket is closed:
if (value == -1) {
// The socket is closed remotely, so close it locally as well:
disconnect();
inputStream = null;
return null;
}
// ... and a bunch of other stuff to handle the actual data
}
EDIT 14-Nov:
This is actually proving to be more of a problem now. Both the client logs and the server logs appear to be sending. But at times the data doesn't appear to come through or if it does it is sometimes coming through 10 - 30 - 60 second delayed.
I can provide more information if required.
When you use BufferedReaders and BufferedWriters things get buffered. How about using the input and output streams directly.. Also, writers are character based, I don't know if you need to send binary data but if so that will be a problem with writers.
I am not sure whether this will be to your any use or not.. but i am giving you the code i used for client server communication..
Client Side:
public class ClientWala {
public static void main(String[] args) throws Exception{
Boolean b = true;
Socket s = new Socket("127.0.0.1", 4444);
System.out.println("connected: "+s.isConnected());
OutputStream output = s.getOutputStream();
PrintWriter pw = new PrintWriter(output,true);
// to write data to server
while(b){
if (!b){
System.exit(0);
}
else {
pw.write(new Scanner(System.in).nextLine());
}
}
// to read data from server
InputStream input = s.getInputStream();
InputStreamReader isr = new InputStreamReader(input);
BufferedReader br = new BufferedReader(isr);
String data = null;
while ((data = br.readLine())!=null){
// Print it using sysout, or do whatever you want with the incoming data from server
}
}
}
Server Code:
import java.io.*
import java.net.*;
public class ServerTest {
ServerSocket s;
public void go() {
try {
s = new ServerSocket(44457);
while (true) {
Socket incoming = s.accept();
Thread t = new Thread(new MyCon(incoming));
t.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
class MyCon implements Runnable {
Socket incoming;
public MyCon(Socket incoming) {
this.incoming = incoming;
}
#Override
public void run() {
try {
PrintWriter pw = new PrintWriter(incoming.getOutputStream(),
true);
InputStreamReader isr = new InputStreamReader(
incoming.getInputStream());
BufferedReader br = new BufferedReader(isr);
String inp = null;
boolean isDone = true;
System.out.println("TYPE : BYE");
System.out.println();
while (isDone && ((inp = br.readLine()) != null)) {
System.out.println(inp);
if (inp.trim().equals("BYE")) {
System.out
.println("THANKS FOR CONNECTING...Bye for now");
isDone = false;
s.close();
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
try {
s.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new ServerTest().go();
}
}
Here is the server code
package echoserver;
import java.net.*;
import java.io.*;
public class EchoServer {
public static void main(String[] args) {
try {
//establish server socket
ServerSocket s = new ServerSocket(1981);
//Thread client connectionsincoming
while (true) {
//wait for incoming connection
Socket incoming = s.accept();
Runnable r = new ThreadedEchoHandler(incoming);
Thread t = new Thread(r);
t.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
package echoserver;
import java.net.*;
import java.util.*;
import java.io.*;
class ThreadedEchoHandler implements Runnable {
public ThreadedEchoHandler(Socket i) {
//initializing socket
incoming = i;
}
public void run() {
try {
try {
//recieve input stream from socket
InputStream inStream = incoming.getInputStream();
//recieve output stream from socket
OutputStream outStream = incoming.getOutputStream();
//Create a scanner from input stream
Scanner scan = new Scanner(inStream);
//Create printer writer from output stream and enabled auto flushing
PrintWriter out = new PrintWriter(outStream, true);
//prompt users on how to exit program soon as a long in into the server
out.println("Enter BYE to exit");
boolean done = false;
//while done is not true and scanner has next line loop
while (!done && scan.hasNextLine()) {
//reading text that came in from the socket
String line = scan.nextLine();
//On the server print the ip address of where the text is coming from and the text they typed
System.out.println("Recieved from " + incoming.getInetAddress().getHostAddress() + ": " + line);
//Echo back the text the client typed to the client
out.println("Echo: " + line);
//if they type BYE in caps terminate there connection and I also trimmed whitespaces
if (line.trim().equals("BYE")) {
done = true;
}
}
} //finally close the socket connection
finally {
incoming.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private Socket incoming;
}
and here is the code for client
package client;
import java.net.*;
import java.io.*;
public class Client {
public static void main(String[] args) throws IOException {
PrintWriter out = null;
try {
Socket s = new Socket(InetAddress.getLocalHost(), 1981);
System.out.println("Connected to server on port 1981");
out = new PrintWriter(s.getOutputStream());
out.println("Hello");
s.close();
} catch (Exception ex) {
System.err.println(ex.getMessage());
}
}
}
Socktes are getting created successfully but when control goes to t.start() method call it is not calling run() method of ThreadedEchoHandler class.
Why is this happening? any idea?
The client writes "Hello" to the PrintWriter. So far, so good.
You may expect that the PrintWriter sends this text directly to the socket, but it doesn't. The documentation from the PrintWriter(OutputStream) constructor says that it creates a PrintWriter without automatic line flushing. This means that you have to call out.flush() whenever you want something to be actually sent.
Until you call out.flush() the text only exists in some internal buffer, and the server will not be able to see it.
My guess would be that the acept statement is blocking forever because no client is connecting to the server. You could wrap accept() in prints to prove or disprove.