I have the following block of code:
public void startListening() throws Exception {
serverSocket = new DatagramSocket(port);
new Thread() {
#Override
public void run() {
System.out.print("Started Listening");
byte[] receiveData = new byte[1024];
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
while (!stopFlag) {
try {
serverSocket.receive(receivePacket);
String message = new String(receivePacket.getData());
System.out.println("RECEIVED: " + message);
} catch (Exception ex) {
System.out.print("Execption :" + ex.getMessage());
}
}
}
}.start();
}
public void stopListening() {
this.stopFlag = true;
}
Suppose I set stopFlag to true. serverSocket.receive(receivePacket); will wait until it receives a packet. What should I do if I want the thread to exit as soon as stopFlag is set to true.
I had the same problem with a socket as well and interrupt() didn't work. My problem was solved by closing the socket. So in the setStop() method (as proposed above) you would have to call serverSocket.close() (you'd obviously have to make serverSocket a class member or something).
It would help if you had some code which included the code where you plan to change the stopFlag. If it is outside of the thread you could probably use a .interrupt() on the thread followed by a .destroy() on the thread. It is not an ideal solution better probably to try and add a timeout on your server socket see setSoTimeout() method of DatagramSocket in the java api.
I'm unsure where the stop flag comes from but anyway, the answer is interrupt.
Thread t;
ServerSoket serverSoket;
public void startListening() throws Exception {
...
serverSocket = new DatagramSocket(port);
t = new Thread()...;
t.start();
...
}
setStop() {
stopFlag = true;
serverSocket.close()
t.interrupt();
}
Use serverSocket.setSoTimeout(t).
Related
I am implementing a multi-threaded client-server application in java. I want to implement JDBC in this program and I want my server to retrieve data from the database whenever it is started. I will store that data in my collection instances, perform manipulations on data and when server completes execution, I need to store the data back to the database. The problem is that the server is in an infinite loop waiting for clients and I am not able to figure out how to make the server stop.
This is my server program:
import java.io.*;
import java.text.*;
import java.util.*;
import java.net.*;
public class Server
{
public static void main(String[] args) throws IOException
{
// server is listening on port 5056
ServerSocket ss = new ServerSocket(5056);
// running infinite loop for getting
// client request
while (true)
{
Socket s = null;
try {
// socket object to receive incoming client requests
s = ss.accept();
System.out.println("A new client is connected : " + s);
// obtaining input and out streams
DataInputStream dis = new DataInputStream(s.getInputStream());
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
System.out.println("Assigning new thread for this client");
// create a new thread object
Thread t = new ClientHandler(s, dis, dos);
// Invoking the start() method
t.start();
}
catch (Exception e) {
s.close();
e.printStackTrace();
}
}
}
}
// ClientHandler class
class ClientHandler extends Thread
{
DateFormat fordate = new SimpleDateFormat("yyyy/MM/dd");
DateFormat fortime = new SimpleDateFormat("hh:mm:ss");
final DataInputStream dis;
final DataOutputStream dos;
final Socket s;
// Constructor
public ClientHandler(Socket s, DataInputStream dis, DataOutputStream dos)
{
this.s = s;
this.dis = dis;
this.dos = dos;
}
#Override
public void run()
{
String received;
String toreturn;
while (true) {
try {
// Ask user what he wants
dos.writeUTF("What do you want?[Date | Time]..\n"+
"Type Exit to terminate connection.");
// receive the answer from client
received = dis.readUTF();
if(received.equals("Exit"))
{
System.out.println("Client " + this.s + " sends exit...");
System.out.println("Closing this connection.");
this.s.close();
System.out.println("Connection closed");
break;
}
// creating Date object
Date date = new Date();
// write on output stream based on the
// answer from the client
switch (received) {
case "Date" :
toreturn = fordate.format(date);
dos.writeUTF(toreturn);
break;
case "Time" :
toreturn = fortime.format(date);
dos.writeUTF(toreturn);
break;
default:
dos.writeUTF("Invalid input");
break;
}
}
catch (IOException e) {
e.printStackTrace();
}
}
try
{
// closing resources
this.dis.close();
this.dos.close();
}
catch(IOException e){
e.printStackTrace();
}
}
}
Here is my client program:
import java.io.*;
import java.net.*;
import java.util.Scanner;
// Client class
public class Client
{
public static void main(String[] args) throws IOException
{
try
{
Scanner scn = new Scanner(System.in);
// getting localhost ip
InetAddress ip = InetAddress.getByName("localhost");
// establish the connection with server port 5056
Socket s = new Socket(ip, 5056);
// obtaining input and out streams
DataInputStream dis = new DataInputStream(s.getInputStream());
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
// the following loop performs the exchange of
// information between client and client handler
while (true)
{
System.out.println(dis.readUTF());
String tosend = scn.nextLine();
dos.writeUTF(tosend);
// If client sends exit,close this connection
// and then break from the while loop
if(tosend.equals("Exit"))
{
System.out.println("Closing this connection : " + s);
s.close();
System.out.println("Connection closed");
break;
}
// printing date or time as requested by client
String received = dis.readUTF();
System.out.println(received);
}
// closing resources
scn.close();
dis.close();
dos.close();
}
catch(Exception e){
e.printStackTrace();
}
}
}
Overview
Great question! To reiterate what was stated in the above comments, you are looking for a server-side shutdown. There are some way of handling this situation, and I can explain it with a brief example.
ExecutorServer
I will run through a modified example based off this example. Below find the server implementation.
class NetworkService implements Runnable {
private final ServerSocket serverSocket;
private final ExecutorService pool;
private final AtomicBoolean shouldExit;
public NetworkService(int port, int poolSize) throws IOException {
serverSocket = new ServerSocket(port);
pool = Executors.newFixedThreadPool(poolSize);
shouldExit = new AtomicBoolean(false); // Thread-safe boolean
}
public void run() { // run the service
try {
// While we should not exit
while(!shouldExit.get()) {
try {
pool.execute(new ClientHandler(serverSocket.accept()));
} catch (SocketException e) {
if(shouldExit.get()) break; // Poison pill has been delivered, lets stop
// Error handling
}
}
} catch (IOException ex) {
pool.shutdown();
}
// Clean up the thread pool
shutdownAndAwaitTermination();
}
}
class ClientHandler implements Runnable {
private final Socket socket;
ClientHandler (Socket socket) { this.socket = socket; }
public void run() {
...
}
...
}
Here you will modify your current Server code to intimidate this structure. You have a similar make up currently but here we have added ExecutorService.
An Executor that provides methods to manage termination and methods that can produce a Future for tracking progress of one or more asynchronous tasks.
By dispatching your ClientHandler to an ExecutorService, you are utilizing a ThreadPool. Although this comes with plenty of benefits, the most significant ones are that you have more control over your multi-threaded service, the ThreadPool will manage thread utilization, and the application efficiency will increase tremendously.
Below is how you would attempt to shutdown and terminate all remaining threads:
void shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}
Now, the question remains how do we shutdown the server? The above code shows a improved structure, but still have the issue of blocking on a serverSocket.accept()!
Solution
There are two ideas that come to mind when thinking of this scenario; a CLI or a GUI. Both have the same semantics, and the decision is ultimately up to you. For purposes of explaining, I will refer to a CLI approach.
Poison Pill
If you implement a new Thread() that handled all incoming commands from the CLI, this thread would act as a poison pill. The idea is to deliver a poison pill to the target such that can wake up/execute and die. The thread will change the shouldExit atomic boolean to true and create a new Socket(serverSocket.getInetAddress(), serverSocket.getLocalPort()).close(); to connect to the ServerSocket and immediately close it. In the above code, the application will no longer be blocking on the serverSocket.accept(). Instead, it will enter the try catch for SocketExceptions and test if a poison pill was utilized; If it was then lets clean up, if not lets error handle.
Timeout
You could also set a timeout on the ServerSocket such that it will throw an exception each time it cannot get a connection in that time interval with myServer.setSoTimeout(2000);. This will throw an InterruptedIOException and can be handled similarly to the poison pill where the flag is changed via a CLI command and it checks if it should exit in the catch block. If it should exit, lets clean up, if not lets error handle.
You can use pattern flag with volatile boolean variable, and you should place it in 'while' - when processing would be finished, turn it to false and the server would stop.
Another way - use thread pools and wait for them to finish in the main thread of your server.
I want to implement a Server which listens endless on a specific port to receive data from many clients (never in parallel, only serial). The first thing I tried is to run the server and then launch a few clients in serial (one after the other).
This sounded very easy to implement, but I actually got into the problem, that the code works only when I run it in debug mode with at least one breakpoint in the server code (but the same fault as when running it normally without a breakpoint), very strange to me.
However here is the server code:
public class TaskExecutionServer {
public TaskExecutionServer(final int port) {
new Thread() {
#Override
public void run() {
try {
int counter = 0;
ServerSocket serverSocket = new ServerSocket(port);
while(true) {
System.out.println("Waiting for client...");
Socket socket = serverSocket.accept();
System.out.println("Accepted");
InputStream inputStream = socket.getInputStream();
ObjectInputStream objectStream = new ObjectInputStream(inputStream);
while(inputStream.available() > 0 ) {
String to = (String)objectStream.readObject();
System.out.println(to);
System.out.println(++counter);
}
objectStream.close();
inputStream.close();
System.out.println("Closing socket");
socket.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
public static void main(String args[]) {
new TaskExecutionServer(2003);
}
}
And here the client code:
public class TaskSenderClient {
public static void main(String args[]){
try{
Socket s = new Socket("localhost",2003);
OutputStream os = s.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(os);
oos.writeObject("test");
oos.close();
os.close();
s.close();
}catch(Exception e){
System.out.println("Client exception");
e.printStackTrace();
}
}
}
this is the console output when running in debug mode with breakpoint in the server code row System.out.println("Accepted");:
Waiting for client...
Accepted
test
1
Closing socket
Waiting for client...
Accepted
test
2
Closing socket
Waiting for client...
Accepted
test
3
Closing socket
Waiting for client...
And the output when running in normal mode / without breakpoints in debug-mode:
Waiting for client...
Accepted
test
1
Closing socket
Waiting for client...
Accepted
Closing socket
Waiting for client...
Accepted
Closing socket
Waiting for client...
I don't get any exception... Can someone help? It's my first attempt to re-use a socket connection in java.
EDIT: Checking inputStream.available returns different values
I just added a System.out.println(inputStream.available()); before the while in server code. This prints
always 7 in debug-mode with breakpoint
7 (in first run) and 0 (in all other attemps) afterwards in non-debug mode / without breakpoints
EDIT 2: First wait until inputStream.available != 0
This solution also works for me. However, I removed this code snippet here, because checking of available() seems not to be the correct way for that! -> see the solution!
EDIT 3: New server code, which uses NonEmptyInputStream which checks per PushbackInputStream for non-empty streams:
As this uses the EOFException it seems not to be an optimal solution to me, so I also removed this code snippet (instead see solution below). The usage of exceptions in "correct" code is discussed in the comments below...
InputStream.available() can return 0 if there is no data yet, meaning the client didn't send some yet or at least it is not arrived yet. If you add a breakpoint the client has more time to send the data.
You can either add logic like your client first sends how many objects it writes, the server reads the amount and then reads that many objects before it stops reading.
Another possibility would be to insert a PushbackInputStream between the ObjectInputStream and the InputStream and then do a read() on the PushbackInputStream, check the result for -1 which means end-of-stream and if it was not -1, use unread() to push the read byte back into the stream before using the ObjectInputStream methods.
Here you have an example of your originally posted class rewritten with the last pattern:
public class TaskExecutionServer {
public TaskExecutionServer(final int port) {
new Thread() {
#Override
public void run() {
try {
int counter = 0;
ServerSocket serverSocket = new ServerSocket(port);
while(true) {
System.out.println("Waiting for client...");
Socket socket = serverSocket.accept();
System.out.println("Accepted");
InputStream inputStream = socket.getInputStream();
PushbackInputStream pushbackInputStream = new PushbackInputStream(inputStream);
ObjectInputStream objectStream = new ObjectInputStream(pushbackInputStream);
for(int i; (i = pushbackInputStream.read()) != -1;) {
pushbackInputStream.unread(i);
String to = (String) objectStream.readObject();
System.out.println(to);
System.out.println(++counter);
}
objectStream.close();
pushbackInputStream.close();
inputStream.close();
System.out.println("Closing socket");
socket.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
public static void main(String args[]) {
new TaskExecutionServer(2003);
}
}
or here again with try-with-resources which is preferable over manually closing AutoClosables.
public class TaskExecutionServer {
public TaskExecutionServer(final int port) {
new Thread() {
#Override
public void run() {
try (ServerSocket serverSocket = new ServerSocket(port)) {
int counter = 0;
while(true) {
System.out.println("Waiting for client...");
try (Socket socket = serverSocket.accept();
InputStream inputStream = socket.getInputStream();
PushbackInputStream pushbackInputStream = new PushbackInputStream(inputStream);
ObjectInputStream objectStream = new ObjectInputStream(pushbackInputStream)) {
System.out.println("Accepted");
for(int i; (i = pushbackInputStream.read()) != -1;) {
pushbackInputStream.unread(i);
String to = (String) objectStream.readObject();
System.out.println(to);
System.out.println(++counter);
}
System.out.println("Closing socket");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
public static void main(String args[]) {
new TaskExecutionServer(2003);
}
}
available() is not a valid test for end of stream. See the Javadoc. You should read from the object stream until EOFException is caught.
I am trying to create a new thread inside a run method of currently running thread. But new thread is not getting started and it is blocking the execution of currently running thread.
Run method of currently running thread.
public void run() {
while(true){
try{
Message message = (Message)objIn.readObject();
System.out.println("Received msg:"+message);
if(message.type.equals("connection")){
if(message.content.equals("true")){
System.out.println("connection successful");
InetAddress senderIp = message.senderIp;
InetAddress receiverIp = message.receiverIp;
System.err.println(senderIp+"------"+receiverIp);
if(senderIp.getHostAddress().equals(receiverIp.getHostAddress())){
//first member of ring topology
System.err.println("first member");
}else{
System.err.println("not the first member");
ClientSideTempClient clientTemp = new ClientSideTempClient(receiverIp);
Thread obj1 = new Thread(clientTemp);
obj1.start();
System.out.println("after starting local client tread...");
}
}else{
System.out.println("something went wrong");
}
}
}catch(Exception e){
System.out.println("Exception:"+e);
}
}
}
Class for new thread:
ClientSideTempClient.java
public class ClientSideTempClient implements Runnable{
public Socket socket;
public ObjectInputStream objIn;
public ObjectOutputStream objOut;
public ClientSideTempClient(InetAddress serverIp){
try{
System.err.println("trying to connect"+serverIp.getHostAddress());
String ipAddress = serverIp.getHostAddress();
socket = new Socket(ipAddress, 9010);
objOut = new ObjectOutputStream(socket.getOutputStream());
objOut.flush();
objIn = new ObjectInputStream(socket.getInputStream());
}catch(Exception e){
System.err.println("Exception in ClientSideTempClient"+e);
}
}
public void sendMessageToLocalServer(Message msg){
try {
objOut.writeObject(msg);
objOut.flush();
System.out.println("Outgoing : "+msg.toString());
}catch(Exception e){
System.out.println("Exception in chatroom_client:"+e);
}
}
#Override
public void run() {
While(true){
System.out.println("Execution started here");
}
}
}
I searched number of related answers for this on google, but i am not getting solution of it. Can anyone guide me to solve this issue?
Your ClientSideTempClient class creates and connects the Socket in its constructor, which is delaying your loop. The Socket and the object streams should be created in its own run() method, i.e. on its own thread.
NB You must catch EOFException and break out of that loop if you get it. Most other IOExceptions are fatal too, except SocketTimeoutException.
It's weird that I use WireShark to test the result, and the result shows that my code can successfully send messages via socket. But my program will throw a Timeout exception even if I receive the message from the server.
I don't know why there is a timeout problem.
My code is simple:
static Timer timer = new Timer();
try {
DatagramSocket c = new DatagramSocket();
c.setBroadcast(true);
byte[] sendData = "messageToServer".getBytes();
try {
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, InetAddress.getByName("255.255.255.255"), 10000);
c.connect(InetAddress.getByName("255.255.255.255"), 10000);
c.send(sendPacket);
} catch(Exception ex) {
System.out.println(ex.toString());
}
timer.schedule(new receiveTask(), 2000);
} catch(Exception ex) {
System.out.println(ex.toString());
}
I use a timer to delay the reception of the message from the server.
The receiveTask class looks like this:
public class receiveTask extends TimerTask {
#Override
public void run() {
// TODO Auto-generated method stub
try {
DatagramSocket c2 = new DatagramSocket();
c2.setSoTimeout(10000);
byte[] recvBuf = new byte[1024];
DatagramPacket receivePacket = new DatagramPacket(recvBuf, recvBuf.length);
String message = "";
while (true) {
c2.receive(receivePacket);
System.out.println("Receive packet from Server");
message=new String(receivePacket.getData()).trim();
System.out.println(message);
System.out.println("Close the connection of server socket");
}
} catch(Exception ex) {
System.out.println(ex.toString());
}
}
}
And a SocketTimeOut exception is thrown in the receiveTask class.
Since the server can send a message to me (tested in WireShark), I don't think the fult is server-side. But what can cause the time-out?
Why the server returns a message to me but I can't receive it in my program?
My Java version is 7, and it makes no difference disabling the firewall on my computer...
Any advice will be appreciated!
Edit: Though the problem isn't about socket.close(); I remvoe the code.
There are a few things you can try.
First of all, try invoke timer.schedule(new receiveTask(), 2000); earlier so that your receiveTask is ready to receive messages before any are sent.
Secondly, move your c.close() statement to a finally clause, especially the one inside the while loop of receiveTask to ensure your sockets don't get closed prematurely. So the codes will look like
DatagramSocket c2 = null;
try{
c2 = new DatagramSocket();
c2.setSoTimeout(10000);
byte[] recvBuf = new byte[1024];
DatagramPacket receivePacket = new DatagramPacket(recvBuf, recvBuf.length);
String message = "";
while(true){
c2.receive(receivePacket);
System.out.println("Receive packet from Server");
message=new String(receivePacket.getData()).trim();
System.out.println(message);
System.out.println("Close the connection of server socket");
}
}catch(Exception ex){
System.out.println(ex.toString());
} finally{
if(c2 != null)
c2.close();
}
If all else failed, try c2.setSoTimeout(0); which will cause the timeout to be set to infinite. But I have a feeling this is only a hack to mask the real problem.
Thanks for everyone's help!
I ask my coworker, and I should do another way: open my own server part to receive the returned messages.
I have heard from others that java may not receive return messages appropriately( maybe that's the reason why I always time out!), since the sending part is okay, just open a server part about listening packages, and I can receive the messages from the server I want, too!
Be aware, you should use the same port of the target server, so you will get your own package that you sent, too. Just filter the sending address of your program.
The server side and full concept is like this:
static DatagramSocket socket2;
public static void main(String[] args) {
// TODO Auto-generated method stub
// Open my own server part to listen messages from broadcast returned
listen();
// Sending UDP broadcast in this part as question implied
}
public static void listen() {
new Thread() {
public void run() {
try{
socket2 = new DatagramSocket(10000);
socket2.setBroadcast(true);
byte[] recvBuf = new byte[1024];
while (true) {
DatagramPacket packet2 = new DatagramPacket(recvBuf, recvBuf.length);
try{
socket2.receive(packet2);
System.out.println("Discovery packet received from: " + packet2.getAddress().getHostAddress());
System.out.println("Packet received; data: " + new String(packet2.getData()));
String message = new String(packet2.getData());
System.out.println("Received: "+message);
}catch(Exception ex){
System.out.println("Cannot receive package: " + ex.getMessage());
}
}
}catch(Exception ex){
socket2.close();
System.out.println("Server side problem occured: " + ex.getMessage());
}
}
}.start();
}
Though you may notice the code is similar, but the concept is different.
And finding what's the problem is better than just find the method to solve problem, I think!
If my opinion is wrong, hope someone can correct it.
I have a problem using DatagramSocket. The problem is that I can't run two Android JUnit tests one after another using DatagramSockets because the second tests throws the following exception:
java.net.BindException: Address already in use
I guess this will be a problem in Activities too, because when the Activity moves from background to foreground, I would probably get the same exceptions.
I'm satisfied if I could either disconnect and reconnect the socket or if I'm able to reuse the old socket but I can't get one of them working. My reusing concept looked like this:
if (serverSocket == null || !serverSocket.isBound()) {
serverSocket = new DatagramSocket(9800);
}
But this doesn't work, same exception. It doesn't even work when I try to reinstantiate it (when I don't negate the 2nd term).
I tried to dis- and reconnect it...
serverSocket.disconnect();
serverSocket = new DatagramSocket(null);
serverSocket.setReuseAddress(true);
serverSocket.bind(new InetSocketAddress("localhost", 9800));
Doesn't work either. Same exception when executing the second test. What can I do to solve this? Here is the whole class:
public class UdpListener extends Thread implements Subject {
private DatagramSocket serverSocket;
private DatagramPacket receivedPacket;
private volatile boolean running = false;
private String sentence = "";
private Observer observer;
private static final String TAG = "UdpListener";
public UdpListener(Observer o) throws SocketException {
observer = o;
if (serverSocket == null || !serverSocket.isBound()) {
serverSocket = new DatagramSocket(9800);
}
}
#Override
public void run() {
setName(TAG);
while (isRunning()) {
byte[] receivedData = new byte[1024];
receivedPacket = new DatagramPacket(receivedData, receivedData.length);
try {
serverSocket.receive(receivedPacket);
}
catch (IOException e) {
Log.w(TAG, e.getMessage());
}
try {
sentence = new String(receivedPacket.getData(), 0, receivedPacket.getLength(), "UTF-8");
if (UdpState.UPDATE.toString().equals(sentence)) {
notifyObserver();
}
}
catch (UnsupportedEncodingException e) {
Log.w(TAG, e.getMessage());
}
}
}
private boolean isRunning() {
return running;
}
public void setThreadRunning(boolean running) throws SocketException {
this.running = running;
if (running) {
// serverSocket = new DatagramSocket(9800);
this.start();
}
else {
// serverSocket.disconnect();
// serverSocket = new DatagramSocket(null);
// serverSocket.setReuseAddress(true);
// serverSocket.bind(new InetSocketAddress("localhost", 9800));
}
}
#Override
public void notifyObserver() {
observer.update();
}
}
ok I was just looking at your code for a while and I just realized you never call:
serverSocket.close();
call it after you call:
serverSocket.disconnect();
and your problem should be solved.
Your code:
if (serverSocket == null || !serverSocket.isBound()) {
serverSocket = new DatagramSocket(9800);
}
Will be short-circuited if the serverSocket instance is null, aka the second check to ensure it is not bound may not get called.
Keep in mind also that there may be a lag period between calling disconnect on your Datagram socket and when the OS actually releases said socket for reuse.