How can I change this code:
public class bingoMachineControl {
void sendCommand(String command) throws IOException {
String ipaddress = "192.168.0.2";
Socket commandSocket = null;
// PrintWriter out = null;
BufferedWriter out = null;
BufferedReader in = null;
BufferedWriter outToDetailFile = null;
FileWriter fstream = null;
String version = "";
int numberOfBallsInGame;
int ledCycleState = 1;
commandSocket = new Socket(ipaddress, 7420);
// out = new PrintWriter(commandSocket.getOutputStream(), true);
out = new BufferedWriter(new OutputStreamWriter(commandSocket.getOutputStream()));
in = new BufferedReader(new InputStreamReader(commandSocket.getInputStream()));
out.write("c");out.flush();
out.write(command);out.flush();
String message = in.readLine();
out.close();
in.close();
commandSocket.close();
}
}
To be able to connect to socket on event (let's say button click), send a message to port on event and then close the socket connection also on event.
Thank you
If you want to keep up the connection, you'll have to make the Socket a class variable.
Then you can access it from each method in that class.
Open the socket when you instantiate the class and close when you are done with sending / receiving.
Mind that you might need to introduce a Thread for keeping the EDT clean from Network communication.
Related
I am making a public connection for a computer
So I was making a connection between two computers in java.
The Code for Client is:-
public class Client {
Socket socket = null;
ServerSocket server = null;
DataInputStream input = null;
DataInputStream in = null; // second is because one takes input from user and one from socket
DataOutputStream output = null;
public Client(String addr,int port)
{
try
{
socket = new Socket(addr,port); //Specifies address and port to connect
input = new DataInputStream(System.in);
output = new DataOutputStream(socket.getOutputStream());
in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
//Code to read coming messages continously and printing them
Runnable read = new Runnable(){
public void run()
{
String line = "";
while (!line.equals("over") // means will work until "over" is recieved
{
line = in.readUTF();
System.out.println("Message Came: "+line);
}
Thread.currentThread().stop(); //To stop current thread so there is no error looping
};
Thread thread = new Thread(read);
thread.start();
String line = ""; //To read message from user
while(!line.equals("over"))
{
line = input.readLine();
output.writeUTF(line);
}
// CLosing connection
socket.close();
in.close();
input.close();
output.close();
}catch(Execption e){
return; // loop for trying again and again to connect
}
}
public static void main(String []args)
{
Client client = new Client("192.168.1.7",25565);
}
}
So this is all the code for Client
All code is same for server except declaring things and initializing them
Constructer will have 1 value (port)
ServerSocket server = null;
While initializing :-
server = new ServerSocket(port);
socket = server.accept();
All works fine until I am using local conne tion that is my ipv4 address
I know I have to port forward the port I am using and I have enabled it
But when I use public ip then it doesnot works
I basically was trying to give a response back from my server if my client sends me the message "Hello mr server". However it doesn't.
Here is my code :
public class Server {
public static final int PORT = 6666;
public static void main(String[] args) throws IOException {
new Server().runServer();
}
public void runServer() throws IOException {
ServerSocket serverSocket = new ServerSocket(PORT);
System.out.println("Server up and ready for connections.....");
while (true) {
Socket socket = serverSocket.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); //for fetching data
String str = br.readLine(); //for fetching data
System.out.println("Client Data:" + str + '\n');
String dataSendingToClient = "gg";
OutputStreamWriter os = new OutputStreamWriter(socket.getOutputStream()); //for sending data
PrintWriter out = new PrintWriter(os); //for sending data
out.println(dataSendingToClient);
os.flush();
if (br.equals("hey mr server")){
OutputStreamWriter os2 = new OutputStreamWriter(socket.getOutputStream()); //for sending data
PrintWriter out2 = new PrintWriter(os); //for sending data
out2.println("hey mr client");
os.flush();
}
}
}
}
You are using br.equals("hey mr server") which will always return false, since br is not a String, but a BufferedReader
Instead you should use your already defined str variable str.equals("hey mr server")
Also note that with your current code, your server will only read one message from the client before moving on to the next connection
If you want your server to read more messages from a single client, you will need to loop until the client sends a disconnect message/the socket closes
while(true)
{
Socket socket = serverSocket.accept();
BufferedReader br = [...];
PrintWriter out = [...];
for(String message = br.readLine(); message != null; message = br.readLine())
{
//do stuff
//message is each line from the client
}
}
If you have multiple clients trying to connect, you will need to multithread the connections
I would recommend a class to enclose the connection details and use Stacks to poll if the client sent data
public static void main(String[] args) //or whatever other method you're running in
{
List<Connection> clients = new ArrayList<Connection>(); //some data structure to hold the clients
//start accepting connections
new Thread(new Runnable()
{
public void run()
{
while(true)
Connection client = new Connection(serverSocket.accept());
}
}).start();
//do something with the clients, read/write/whatever
}
private class Connection extends Runnable
{
private BufferedReader reader;
private PrintWriter writer;
private Queue<String> messages;
public Connection(Socket s)
{
reader = [...];
writer = [...];
messages = new LinkedList<String>();
}
public void run()
{
//just keep reading
while(true)
messages.add(reader.readLine();
}
public String read()
{
messages.poll();
}
public void write(String msg)
{
writer.write(msg);
writer.flush();
}
}
Note: take that as rough pseudocode
I have this client and server programs.
The client get a command from user, and send it to the server, and the server return the result (output of the command) to the client.
I have 2 classes Command and CommandResult (represents the command and the result), and I'm passing them as json with ObjectInput(/Output)Stream.
This is the code:
Client
Socket socket = new Socket("localhost", 1111);
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
while (true) {
//get command from user
Scanner scanner = new Scanner(System.in);
System.out.println("Enter command:");
String cmd = scanner.nextLine();
Command command = new Command(cmd);
//send the command as json
String jsonCommand = new Gson().toJson(command);
out.writeObject(jsonCommand);
out.flush();
//get and print the result
String jsonCommandResult = (String) in.readObject();
CommandResult commandResult = new Gson().fromJson(jsonCommandResult, CommandResult.class);
System.out.println(commandResult.getOutput());
}
Server
ServerSocket serverSocket = new ServerSocket(1111);
Socket socket = serverSocket.accept();
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
while (true) {
//read the command
String cmd = (String) in.readObject();
Command command = new Gson().fromJson(cmd, Command.class);
//run() method will run the command with java Process and return the result
CommandResult commandResult = command.run();
//sent the result back to the client as json
String jsonCommandResult = new Gson().toJson(commandResult);
out.writeObject(jsonCommandResult);
out.flush();
}
Now, this is working fine when I have one client.
But if I'm trying to run a second instance of the client program, while the first one is still in the loop, it hangs in the ObjectInputStream constructor. (third line)
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
As I understand from the documentation, the constructor block until the corresponding ObjectOutputStream has been created.
Creates an ObjectInputStream that reads from the specified InputStream.
A serialization stream header is read from the stream and verified.
This constructor will block until the corresponding ObjectOutputStream
has written and flushed the header.
In my case the server has not accept the new client yet, and therefore the ObjectOutputStream has not been created.
Now, what I want is to throw exception if a new client trying to connect while other client is connected to the same port.
But I can't figure it out how to check if the port is now in use before calling this constructor.
As #Kayaman proposed in the comments, I created a Runnable class handles the current client.
Then in the server, I'm looping on serverSocket.accept() and allowing only one client at the time by starting a new thread for the first client, and check whether the current client is finished his communication or not.
Here is the final Server class.
public class Server {
private static final int SERVER_READY = 1;
private static final int SERVER_BUSY = 0;
public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException {
int port = Integer.valueOf(args[0]);
System.out.println(String.format("Starting server on port %s", port));
ServerSocket serverSocket = new ServerSocket(port);
System.out.println("Server is ready");
Thread clientThread = null;
while (true) {
Socket clientSocket = serverSocket.accept();
OutputStream os = clientSocket.getOutputStream();
if (clientThread != null && clientThread.isAlive()) {
os.write(SERVER_BUSY);
continue;
}
os.write(SERVER_READY);
System.out.println(String.format("Client connected: %s", clientSocket.getInetAddress()));
clientThread = new Thread(new ClientWorker(clientSocket));
clientThread.start();
}
}
public static class ClientWorker implements Runnable {
private final Socket clientSocket;
ClientWorker(Socket clientSocket) {
this.clientSocket = clientSocket;
}
#Override
public void run() {
try {
handleClient();
} catch (Exception e) {
e.printStackTrace();
}
}
private void handleClient() throws IOException, ClassNotFoundException {
try {
ObjectOutputStream out = new ObjectOutputStream(clientSocket.getOutputStream());
ObjectInputStream in = new ObjectInputStream(clientSocket.getInputStream());
while (true) {
System.out.println("Waiting for command..");
String cmd = (String) in.readObject();
System.out.println(String.format("Command received:\n %s", cmd));
if (cmd.equals("exit"))
break;
Command command = new Gson().fromJson(cmd, Command.class);
CommandResult commandResult = command.run();
String jsonCommandResult = new Gson().toJson(commandResult);
System.out.println(String.format("Sending response:\n %s", jsonCommandResult));
out.writeObject(jsonCommandResult);
out.flush();
}
//in case the client connection has closed, we want to end the while loop and accept a new client
} catch (EOFException | SocketException e) {
}
System.out.println("Connection has been closed");
clientSocket.close();
System.out.println("Server is ready");
}
}
}
In the Client class, I check if the Server is ready or not.
Socket socket = new Socket(HOST, PORT);
int status = socket.getInputStream().read();
if (status != SERVER_READY)
throw new Exception(String.format("Failed to connect to server %s:%s, Server is busy", HOST, PORT));
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
....
....
Here I am creating a thread to check for a server response every 2 seconds, the issue is that the client.monitorResponse() is a readLine() method and will not continue until a response is received.
client = new ClientObject("localhost");
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
try {
String response = null;
if(!(response = client.monitorResponse()).isEmpty()) {
System.out.println("Response: " + response);
} catch (Exception e) {
e.printStackTrace();
}
}
}, 2000, 2000);
I am sending the response via the Server like so (where client is a established Socket):
public SocketObject(Socket client, int numberOfClients) throws Exception {
socket = client; // the .accept() socket is passed through
// this is because I assign them ID's for later use (I hold an ArrayList of sockets)
this.clientId = numberOfClients;
// both these are static to the class
outputStream = new PrintWriter(client.getOutputStream());
inputStream = new BufferedReader(new InputStreamReader(client.getInputStream()));
}
public void sendResponse(String response) {
outputStream.println(response);
}
I am then picking the response up via the client Socket that has connected to the server:
public ClientObject(String hostname) throws IOException {
// socket is static to this class
socket = new Socket(hostname, 4444);
System.out.println("Connected to " + hostname + " on port 4444...");
// both static to this class
outputStream = new PrintWriter(socket.getOutputStream(), true);
inputStream = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println("Successfully started a stream on " + hostname);
this.hostname = hostname;
}
public String monitorResponse() throws Exception {
System.out.println("Listening for a response...");
return inputStream.readLine();
}
The debug console only displays the Listening for a response... output once which is telling me that it doesn't get past the inputStream.readLine() method in-side the Thread. Is there anyway I can add a timeout on the BufferedReader? I have tried multiple solutions like adding a .setSoTimeout() to the socket before creating the BufferedReader but all that did was close the connection/socket after the specified time.
Any help would be appreciated.
You should use a non-blocking (NIO) request and read chunks looking for newlines in-between. Typically in Java you just have to look for the NIO version of the Stream class you are using and use it to check every N seconds for new content. In your case with minimal modifications you can use the less fancy and efficient method of blocking calls with BufferedReader.ready() to prevent blocking:
String partialLine="";
public static String monitorResponse() throws Exception {
System.out.println("Listening for a response...");
int nextByte;
String nextChar;
while (inputStream.ready()) {
nextByte = inputStream.read();
nextChar = Character.toString ((char) nextByte);
partialLine += nextChar;
if ("\n".equals(nextChar)) {
String line = partialLine;
partialLine = "";
return line.replace("\r\n", "");
}
}
return "";
}
Check out http://tutorials.jenkov.com/java-nio/nio-vs-io.html for more info.
Is there anyway I can add a timeout on the BufferedReader?
No, but you can set a timeout on the Socket, with Socket.setSoTimeout().
I have tried multiple solutions like adding a .setSoTimeout() to the socket before creating the BufferedReader but all that did was close the connection/socket after the specified time.
No it doesn't close the socket. It throws SocketTimeoutException, which you should catch and handle as pertinent. If the socket is being closed, you're closing it. Solution: don't.
This question already has answers here:
Java multiple file transfer over socket
(3 answers)
Closed 6 years ago.
In this code I use multiple times of retrieve input-output data from two nodes. ... when I use more than two times input output stream it generated this type of error while running this code I need different input and output and that I want to store but unfortunate if I used more than three-time input/output stream it show error
public class Server {
private static Socket socket;
public void connect() throws IOException{
int port = 25000;
ServerSocket serverSocket = new ServerSocket(port);
System.out.println("Server Started and listening to the port 25000");
socket = serverSocket.accept();
}
//Server is running always. This is done using this while(true) loop
//Reading the message from the client
public void first() throws IOException{
connect();
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String number = br.readLine();
System.out.println("Message received from client is "+number);
//Multiplying the number by 2 and forming the return message
String returnMessage;
try
{
int numberInIntFormat = Integer.parseInt(number);
int returnValue = numberInIntFormat*2;
returnMessage = String.valueOf(returnValue) + "\n";
}
catch(NumberFormatException e)
{
//Input was not a number. Sending proper message back to
client.
returnMessage = "Please send a proper number\n";
}
second();
String e=br.readLine();System.out.println(e);
}
public void second() throws IOException{
//Sending the response back to the client.
String returnMessage="Second";
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
bw.write(returnMessage);
System.out.println("Message sent to the client is "+returnMessage);
bw.flush();
}
public static void main(String args[]) throws IOException{
Server obj = new Server();
obj.first();
// obj.second();
}public class Server {
private static Socket socket;
public void connect() throws IOException{
int port = 25000;
ServerSocket serverSocket = new ServerSocket(port);
System.out.println("Server Started and listening to the port 25000");
socket = serverSocket.accept();
}
//Server is running always. This is done using this while(true) loop
//Reading the message from the client
public void first() throws IOException{
connect();
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String number = br.readLine();
System.out.println("Message received from client is "+number);
//Multiplying the number by 2 and forming the return message
String returnMessage;
try
{
int numberInIntFormat = Integer.parseInt(number);
int returnValue = numberInIntFormat*2;
returnMessage = String.valueOf(returnValue) + "\n";
}
catch(NumberFormatException e)
{
//Input was not a number. Sending proper message back to client.
returnMessage = "Please send a proper number\n";
}
second();
String e=br.readLine();System.out.println(e);
}
public void second() throws IOException{
//Sending the response back to the client.
String returnMessage="Second";
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
bw.write(returnMessage);
System.out.println("Message sent to the client is "+returnMessage);
bw.flush();
}
public static void main(String args[]) throws IOException{
Server obj = new Server();
obj.first();
// obj.second();
}
public class client {
private static Socket socket;
//public void connect() throws UnknownHostException, IOException{
//}
public void first() throws IOException{
String host = "localhost";
int port = 25000;
InetAddress address = InetAddress.getByName(host);
socket = new Socket(address, port);
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
String number = "2";
String sendMessage = number + "\n";
bw.write(sendMessage);
bw.flush();
System.out.println("Message sent to the server : "+sendMessage);
String sendMessage1="3333";
bw.write(sendMessage1);
bw.flush();
//second();
}
public void second1() throws IOException{
//Get the return message from the server
InputStream is = socket.getInputStream();
InputStreamReader isr;
isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String message = br.readLine();
System.out.println("Message received from the server : " +message);
socket.close();
}
public static void main (String argd[]) throws IOException{
client obj1 = new client();
obj1.first();
}
-----------------------------------------
error
Message received from client is 2
Message sent to the client is Second
Exception in thread "main" java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:209)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
InputStream and OutputStream are intended to work with a single source and destination. Once you obtain an InputStream that reads from file/socket/whatever source you can use it for multiple consecutive reads. But once you are done reading from that source you need to invoke close() method on your stream.
Not closing your stream is classic reason for a memory leak in Java. In fact for that reason you ALWAYS expected to surround the usage of your source with try catch and always invoke close() method in finally statement. So to insure that it is always invoked. Further more, since close() method itself can cause an Exception, within final statement you need to surround it with its own try-catch. Starting from java 7 there is a new feature called "try with resources" that deals with this particular issue.
Please read about it here