We're doing a socket programming project for our Uni. We are developing a file sync software, and we're currently stuck with sending and receiving messages sent over socket.
So, when testing on local machine, code works perfectly. But, when we simulate the server-client environment over LAN and WiFi we get null pointer exception. The files are being sent in chunks so only 5-10 of them pass through.
I guess there is some issue regarding the total time needed for sending messages over socket, and that this is the reason why we get the exception.
Method for sending messages sends the message and starts the timer thread. If no answer is received from the server within 2 seconds, the message will be sent again. Here is the code for sending messages:
public static void sendMessage(final byte[] message) {
try {
final Thread timer = new Thread() {
#Override
public void run() {
try {
System.out.println("timer started");
sleep(1500);
System.out.println("timer timeout");
sendMessage(message);
} catch (Exception e) {
e.printStackTrace();
}
}
};
Thread thread = new Thread() {
#Override
public void run() {
try {
byte[] buffer = new byte[1250];
serverByteStream.read(buffer);
timer.stop();
} catch (Exception e) {
}
}
};
timer.start();
serverByteStream.write(message);
thread.start();
} catch (Exception e) {
}
}
When you recursively call sendMessage() again, you should kill the thread thread also.
Please post the full stacktrace and code where the error occurs also.
Related
I have to implement (in the server side) the quit command which disconnects any clients still connected and closes the server.
Here the server code.
public class Server {
public static void main (String args []) {
if (args.length < 1) {
System.err.println("Usage: java Server <port>");
return;
}
int port = Integer.parseInt(args[0]);
try {
ServerSocket listener = new ServerSocket(port);
Files input = new Files();
while (true) {
System.out.println("Listening...");
Socket s = listener.accept();
System.out.println("Connected");
Thread clientHandlerThread = new Thread(new ClientHandler(s,input));
clientHandlerThread.start();
}
} catch (IOException e) {
System.err.println("Error during I/O operation:");
e.printStackTrace();
}
}
}
how can the server accept command line instructions while it is running?
First of all, you have to keep track of all the clients that you create by putting their instances in a list so that when you're going to shutdown everything, you could access them and tell them to finish their job.
And about how to tell the thread instances to do that, you should call their interrup() method to inform them that they should finish/stop whatever it's doing. Calling the interrupt() method on a thread leads an InterruptedException in the thread that you should handle and gracefully finish whatever you're doing.
For example if you have something like this in the run method of your ClientHandler:
while (true) {
try {
Thread.sleep(interval);
} catch (InterruptedException e){
Thread.currentThread().interrupt();
System.out.println(
"We've been asked to finish up the communication. Bye! ;)");
}
// do your business
}
This was of course a very simplified scenario to demonstrate the overall approach. You should be able to find tons of tutorials online about how to use the interrupt.
I'm writing a program that:
Sends ping packets to other processes running the same program
The process sends a response to the ping from (1)
If a process does not receive a response in X seconds, then call a method to update states
So I currently only have 1 Datagram socket that handles both sending and receiving the packets. The way I handled the ping timeout was calling setSoTimeout on the socket and blocking on the receive right after I send the ping packet to another process.
public MyProgram {
private DatagramSocket socket;
public MyProgram() {
socket = new DatagramSocket("localhost", 12345);
Thread sendingThread = new Thread(new Runnable() {
public void run() {
// call sendLoop method
}
}
Thread receiveThread = new Thread(new Runnable() {
public void run() {
// call receiveLoop method
}
}
}
public void sendLoop() {
while (true) {
/*
send ping to other process
*/
// now wait until it replies with ACK
try {
socket.receive(...);
} catch (SocketTimeoutException e) {
// call method to update state
}
}
}
// ... more code ...
}
Now the problem is when I write receiveLoop (separate thread to sendLoop) which waits for incoming ping packets from other processes
public void receiveLoop() {
while (true) {
socket.receive(...);
// call methods to reply to the ping
}
}
How can I wait for a response to my own ping, whilst waiting for incoming pings on another thread? I figured this approach would be bad because the ping response could arrive on the other thread?
Can you even simultaneously call receive on the same UDP socket in different threads?
Is there a way to solve this without having to create another UDP socket? Many thanks!
Suppose a client sends server a request. The server responds with an ACK. However, if the server does not respond within two seconds, the code terminates.
socket.receive(ack);
is a blocking call. However, I assumed that if I disconnected the socket in timer task, this blocking call will be ignored now and the code will continue. But it still acts as a blocking call, so this code does not function the way I want it to. Is there some other way to implement the same thing?
Timer timer = new Timer();
TimerTask timeout = new TimerTask() {
public void run() {
try {
socket.disconnect();
}
catch (Exception e) {
e.printStackTrace();
}
}
};
socket.send(request);
timer.schedule(timeout, 2000);
socket.receive(ack);
String data = new String(ack.getData());
if ((data.substring(0,3)).equals("ACK")) {
received = true;
timer.cancel();
}
if (received) {
//rest of the code
}
else {
return;
}
No need for a Timer object. You can set the timeout in the socket and catch the potential timeout exception to handle the closing / termination of the program.
socket.send(request);
socket.setSoTimeout(20000);
try {
socket.receive(ack);
} catch (SocketTimeoutException e) {
...
}
Maybe you need to set SOCKET TIMEOUT like this:
It is timeout for incoming data:
Socket s = new Socket(address, port);
s.setSoTimeout(timeout);
You can also set a connection timeout if you can't connect with server in some resonable time:
s.connect(endpoint, timeout)
it will throw an TimeoutException after timeout time, and break the blocking execution;
Im running Netty and i need to read some messages from the client.
Then i need to execute some actions in the Server, then send a response to the client.
Maybe the Client need to answer again to the server.
I think all this have to happend in the same Thread.
How can i do this in the Netty server?
Im testing the code below using Telnet but i cant get a response from the server.
If i Comment the first block, (Read message block), so i start to receive the response in the Telnet console.
#Override
public void channelRead(ChannelHandlerContext ctx, Object msg) { // (2)
// Read the message sent from client.
try{
ByteBuf in = (ByteBuf) msg;
try {
while (in.isReadable()) { // (1)
System.out.print((char) in.readByte());
System.out.flush();
}
}
catch(Exception e){
System.out.println("---------------- Reading Exception ----------------");
e.printStackTrace();
}finally{
//ReferenceCountUtil.release(msg);
}
// treat the received message
if(msg.equals("teste")){
// do Something...
}
//Answer to the client
try {
ctx.write(msg); // (1)
ctx.flush(); // (2)
}
catch(Exception e){
System.out.println("---------------- Writing Exception ----------------");
e.printStackTrace();
}
}
finally {
//ReferenceCountUtil.release(msg); // (2)
}
}
after the while loop: while (in.isReadable()) {...}, the msg ByteBuf is not readable anymore, so nothing will be written to the client via ctx.write(msg)
I have one web application from which I can start respective testing process which is in another Java app. I am using Socket Programming for communication between Web app and Java app.
When I request for specific process from web app then SocketServer from Java app hears request and start one thread for Testing process.
Testing process will initialize FirefoxDriver and start browser and do further test process.
My problem is, when I request for another process with different process name then It again creates second thread and start firefox browser but this time it is not considering my second process, it started to do same process which is first thread have.
I do not understand what to do...For every process I created a new thread but further it will doing same process.
My inputs are correctly received at Java app.
Please help me How can I do the concurrent thread safe processing?
I am using GWT,Java, Seleniun FirefoxDriver.
here is the Server code which is running in background and listen client request:
static final int PORT = 6789;
public static void main(String args[]) {
ServerSocket serverSocket = null;
Socket socket = null;
try {
InitializeApplication application = new InitializeApplication();
application.initialize();
serverSocket = new ServerSocket(PORT);
} catch (Exception e) {
log("Exception in SocketServerExecutor !!!",e);
}
while (true) {
try {
socket = serverSocket.accept();
} catch (Exception e) {
log("Exception in SocketServerExecutor !!!",e);
}
Thread thread = new Thread(new SocketServerThread(socket));
thread.start();
}
}
and this is the Thread which start process:
private Socket client;
public SocketServerThread(Socket serverSocket) {
this.client = serverSocket;
}
/**
* Starts appropriate process depending on process name from input.
* Input string contains:
* process name
*/
public void run() {
DataOutputStream outputStream = null;
String param = null;
try{
log("Just connected to "+ client.getRemoteSocketAddress());
try {
while ((param = in.readUTF()) != null){
log("got parameteres from client (i.e. from web app): "+param);
break;
}
} catch (Exception e) { }
if(param!=null && !param.isEmpty()){
String process = params[0];
ProcessManager manager = new ProcessManager();
if(process.equals("testUser"))
manager.startUserProcess(process);
else if(process.equals("testCustomer"))
manager.startCustomerProcess(process);
}
}catch(Exception exc){
if(exc instanceof SocketTimeoutException)
log("Socket timed out! [SocketServerThread]",exc);
else if(exc instanceof BindException)
log("BindException in SocketServerThread !!!",exc);
log(Level.SEVERE, "Exception in SocketServerThread !!!",exc);
}
}
and this is ProcessManager:
public void starUserProcess(String siteName) {
ExecutorService executerService = null;
try{
Callable<Object> callable = new ProcessThread(siteName);
executerService = Executors.newCachedThreadPool();
Future<Object> future = executerService.submit(callable);
future.get();
log("[ProcessManager] Process completed for "+process);
System.exit(0);
}catch (Exception e) {
log("[ProcessManager]::Exception");
log(ex);
}
}
ProcessThread will initialize all required things and Firefox browser and start process.
Client is new every time which contains input.
One of two things that I can thing of off the top of my head could be happening.
You are passing a paramater into your run() function that links back to the initial thread or...
You are using a shared variable that is accessible to all threads and the variable is either not being updated properly, or not being updated at all.
If you could include an SSCCE, that would help us determine where the problem truly lies.
Got the solution: I created the ExecutorService using newSingleThreadExecutor() instead of newCachedThreadPool() and also setDeamon(True) for every newly created ServerThread.
Here is the Executor documentation