I want to write a HTTP server with a long time response.
I prepared a loop:
serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 8000));
while (serverSocketChannel.isOpen()) {
try {
System.out.println("Waiting...");
SocketChannel socketChannel = serverSocketChannel.accept();
System.out.println("The new connection is open ;)");
} catch (IOException ex) {
System.out.println(ex.getMessage());
Logger.getLogger(ServerHttp.class.getName()).log(Level.SEVERE, null, ex);
}
}
I want to catch new connection from a user's browser, put it into a list, and then another thread will take it and will parse it.
But I have problem on the beginning: the code above is freezing in the method serverSocketChannel.accept().
When I add socketChannel.close() everything is working correctly, but I don't want to close the connection in this place, because I need a long time response.
Look at the javadoc for ServerSocketChannel:
"If this channel is in non-blocking mode then this method will immediately return null if there are no pending connections. Otherwise it will block indefinitely until a new connection is available or an I/O error occurs."
This seems to describe the "freezing" you are experiencing.
You can open your ServerSocketChannel in non-blocking mode:
serverSocketChannel.configureBlocking(false);
Related
Edit: I've found the problem ( see answer below )
I'm trying to write an Android application to send data to a running termux instance via TCP.
In termux, I have netcat listening for incoming TCP connections and printing data to stdout using the command nc -l localhost 8080.
In my android app, I have a thread that reads in strings from a blocking queue and writes them out to a socket connectd to the address that netcat is listening on. The relevant code is the following:
runnable = () -> {
Socket socket = null;
OutputStream socketOutStream = null;
while (running) {
try {
if (null==socket) {
socket = new Socket();
socket.setTcpNoDelay(true);
socket.setKeepAlive(true);
socket.connect(new InetSocketAddress("127.0.0.1", 8080), 2000);
socketOutStream = socket.getOutputStream();
socketOutStream.write("Hello, Server!".getBytes()); // [1] Works!!
socketOutStream.flush();
}
String message = queue.take();
socketOutStream.write(message.getBytes()); // [2] Doesn't work!!?
socketOutStream.flush();
socketOutStream.close();
Log.i(TAG, "We wrote 'Button Clicked!' to the socket I think.");
// running=false;
}
catch (IOException e) {
Log.e(TAG, e.toString());
socket = null;
}
catch (InterruptedException e) {
Log.e(TAG, e.toString());
Log.i(TAG, "Exiting socket sending loop.");
running = false;
}
}
};
Thread thread = new Thread(runnable);
thread.start();
I'm trying to figure out why the initial data sent to netcat at the line marked [1] is actually received and displayed inside termux, but any subsequent data sent at [2] is not. The incoming strings fetched from the queue are certainly not empty.
Additionally, if I move the socket instantiation and connection logic to occurr until after queue.take() returns, I see a SocketTimeoutException via adb log output.
I would like to understand why it should make any difference whether either of these operations shoud occurr before or after the queue.take() operation returns.
I was eventually able to resolve the issue with the TCP socket hanging by attaching the socket to a foreground service as opposed to a background service which is how it was running in the first instance. It seems Android background services are liable to have TCP communications delayed or buffered in order to economize battery usage.
I am experiencing problems when using a UDP datagram packet, in the program I bind a UDP port and listen messages on it. This normally works fine, but if the port remains idle for a long time, the program automatically terminates the UDP socket. Unfortunately, the log file is huge and it is difficult to find the exception. Please help me find a way to keep the UDP port alive forever. Thanks in advance.
Here is my code:
socket = new DatagramSocket(port);
setBindSocket(true);
socket.setSoTimeout(60000);
while(isBindSocket()) {
try {
byte[] buffur = new byte[512];
DatagramPacket inputPacket = new DatagramPacket(buffur, buffur.length);
inputPacket.setLength(buffur.length);
socket.receive(inputPacket);
byte [] bString = inputPacket.getData();
String hString = new String(bString);
} catch (SocketTimeoutException ste) {
} catch (Exception e) {
e.printStackTrace();
}
}
The following statement changes the socket's behavior when receiving - if no datagram arrives in 60 seconds, a SocketTimeoutException is thrown.
socket.setSoTimeout(60000);
Maybe I have misunderstood your question.
You're going to have to find that exception. Unless you set a read timeout, the read method will block forever.
I try to overcome a user disconnection detection on the server side using read timeout.
This is part of my code:
try {
socket.setSoTimeout(3000);
in = new DataInputStream(socket.getInputStream());
out = new DataOutputStream(socket.getOutputStream());
usr = new User(in.readUTF());
usr.connectUser();
int i=0;
while(true){
try{
i = in.readInt();
}
catch(SocketTimeoutException e){
System.Out.Println("Timeout");
// user connected, no data received
}
catch(EOFException e){
System.Out.Println("Disconnected");
// user disconnected
}
}
}
catch(Exception e){
// other exceptions
}
the code works fine except the "user disconnected" issue.
i want to catch the timeout exception and just continue waiting for data
but only if the client still connected.
why i never get other exception than SocketTimeoutException?
shouldn't i get IOException while in.readInt() can't use the socket because client disconnected?
is there any other simple way to detect user disconnection?
i mean as unwanted disconnection, like user had suddenly wifi shutdown etc...
thanks,
Lioz.
If the client didn't write anything within the timeout period, you get a SocketTimeoutException. If he disconnected instead of writing anything, you get an EOFException. Catch them separately. If you didn't get an EOFException, he didn't disconnect.
In my server located in a android device , if the number number of clients exceeds a specific number then the server close the socket. But in my client(other android device) i get a force close. How can i handle it gracefully?
Here is the connect part on my client:
serverIpAddress = serverIp.getText().toString();
if (!serverIpAddress.equals(""))
{
try
{
InetAddress serverAddr = InetAddress.getByName(serverIpAddress);
SocketAddress sockaddr = new InetSocketAddress(serverAddr, 5000);
nsocket = new Socket();
nsocket.connect(sockaddr);
}catch(Exception e){
Log.i("Connect", "Connection Error");
}
if (nsocket.isConnected()){
score.setText("Your score is " + sc);
serverIp.setVisibility(View.GONE);
connectPhones.setVisibility(View.GONE);
enterIP.setVisibility(View.GONE);
Log.i("Connect", "Socket created, streams assigned");
Log.i("Connect", "Waiting for inital data..." + nsocket.isConnected());
receiveMsg();
}
Keep checking the socket connection is still open or not using isClosed() within an infinite loop, when server closes its connection, the isClosed() gets true, and then display a message or toast giving your desired reason to the user.
Sounds like whatever you are using to read the socket is a blocking read, and throws an exception when the socket closes and it is stuck at that read. Make sure that read is in a try block, and use the catch/finally to gracefully exit whatever you are doing at that moment.
I'm trying to allow multiple connections to a little Java server type app. It works fine as is, but if one connection opens and then hangs, all subsequent connections will hang. I'm not sure how to go about handling each connection, up to about 20 concurrent ones in their own thread while keeping track of which thread belongs to which client etc. The code I have so far is:
private void init() {
try {
// Create the server socket channel
ServerSocketChannel server = ServerSocketChannel.open();
// nonblocking I/O
server.configureBlocking(false);
// host-port
server.socket().bind(new InetSocketAddress(host, port));
System.out.println("Server connected on " + host + ":" + port);
// Create the selector
Selector selector = Selector.open();
// Recording server to selector (type OP_ACCEPT)
server.register(selector, SelectionKey.OP_ACCEPT);
// Infinite server loop
for (;;) {
// Waiting for events
selector.select();
// Get keys
Set keys = selector.selectedKeys();
Iterator i = keys.iterator();
// For each keys...
while (i.hasNext()) {
SelectionKey key = (SelectionKey) i.next();
// Remove the current key
i.remove();
// if isAccetable = true
// then a client required a connection
if (key.isAcceptable()) {
// get client socket channel
SocketChannel client = server.accept();
// Non Blocking I/O
client.configureBlocking(false);
// recording to the selector (reading)
client.register(selector, SelectionKey.OP_READ);
continue;
}
// then the server is ready to read
if (key.isReadable()) {
SocketChannel client = (SocketChannel) key.channel();
// Read byte coming from the client
int BUFFER_SIZE = 32;
ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
try {
client.read(buffer);
} catch (Exception e) {
// client is no longer active
e.printStackTrace();
continue;
}
buffer.flip();
Charset charset = Charset.forName("ISO-8859-1");
CharsetDecoder decoder = charset.newDecoder();
CharBuffer charBuffer = decoder.decode(buffer);
Handler dataHandler = new Handler();
client.write(ByteBuffer.wrap(dataHandler.processInput(charBuffer.toString()).getBytes()));
client.socket().close();
continue;
}
}
}
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
Whenever I need to write a socket server I avoid using low-level JVM classes because of the need to handle all the nitty-gritty details.
Instead I use Apache Mina. This ia a Java library for writing high-performance non-blocking multi-threaded socket servers.
An added benefit of using Mina is that it enforces clean architecture (IoFilters, protocol decoders) which makes your code more modular and makes it more maintainable.
Unless you really want to write an NIO server as a learning exercise I would recommend using Netty. Like Mina that Peter mentioned it is also a library for writing high performance servers.
I recently moved from using my own NIO code to this library and it has made my code so much cleaner.
My solution i Netty and Executor which creates ThreadPool.
You simply add handler do Netty's pipeline, which call executor witch ChannelBuffer as a parameter.
Than every client request will be processed by separate thread.
Look at the examples