Java Socket selector doesnt switch to write state - java

We have implemented solution based on selector
like
#Override
public void run() {
super.run();
while (session.isConnectionAlive()) {
try {
// Wait for an event
selector.select();
} catch (IOException e) {
log.error("Selector error: {}", e.toString());
log.debug("Stacktrace: ", e);
session.closeConnection();
break;
}
handleSelectorkeys(selector.selectedKeys());
}
executorService.shutdown();
log.debug("Ucp worker stopped");
}
private void handleSelectorkeys(Set<SelectionKey> selectedKeys) {
Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
while (keys.hasNext()) {
SelectionKey selKey = keys.next();
selector.selectedKeys().remove(selKey);
try {
processSelectionKey(selKey);
} catch (IOException e) {
// Handle error with channel and unregister
selKey.cancel();
log.error("Selector error: {}", e.toString());
log.debug("Stacktrace: ", e);
}
}
}
public void processSelectionKey(SelectionKey selKey) throws IOException {
// Since the ready operations are cumulative,
// need to check readiness for each operation
if (selKey.isValid() && selKey.isConnectable()) {
log.debug("connectable");
// Get channel with connection request
SocketChannel sChannel = (SocketChannel) selKey.channel();
boolean success = sChannel.finishConnect();
if (!success) {
// An error occurred; handle it
log.error("Error on finish");
// Unregister the channel with this selector
selKey.cancel();
}
}
if (selKey.isValid() && selKey.isReadable()) {
readMessage(selKey);
}
if (selKey.isValid() && selKey.isWritable()) {
writeMessage(selKey);
}
if (selKey.isValid() && selKey.isAcceptable()) {
}
}
It works fine till we start sending around 100 messages per sec and receive also around 100 response and 100 income messages and send 100 our responses (around 400 messages per sec in both ways) With such load from time to time due to unknown issue on other side our partner cut connection. We reestablish connection but for some reason selector doesn't switch to write state only read. We receive a lot messages on read but cannot send anything.
Any ideas? Is it OS issue issue on our side with connection. How does selector works? Switch from read to write by some logic or spontaneously?

There is no such thing as 'switch [from read] to write state'. A socket can be readable and writable at the same time, and a Selector doesn't 'switch': it merely reports which states exist on the socket.
If the write event never triggers, it is because the socket send buffer is full, which indicates that the peer isn't reading from the connection.

Related

AWS SQS : All messages are getting picked at once and moved to in-flight However I want them to be processed one by one

I have created an SQS consumer which is supposed to pick a single message at once, process(takes 20 minute on an avg) it and then acknowledge. However what it is doing is, it picks all the messages(available in queue) at once and move them in flight(most annoying part) and then it process one by one but the last message would still remain in flight till visibility timeout expires (though all other messages would have processed).
I have tried giving a timeout in receive but that didn't work. I am using the below code to poll the queue and process the messages accordingly
public void startReceiving(String sqsServiceUrl, String queueName) throws JMSException {
String msgAsString = StringUtils.EMPTY;
do {
tryToReconnect(sqsServiceUrl, queueName);
msgAsString = receiveMessage(getMessageConsumer(sqsServiceUrl, queueName));
} while(!StringUtils.equalsIgnoreCase(msgAsString, "exit"));
}
private String receiveMessage(MessageConsumer consumer) throws JMSException {
Message message = consumer.receive(0);
String msgAsString = StringUtils.EMPTY;
} else {
try {
msgAsString = ((SQSTextMessage) message).getText();
/*Do some processing and overwrite msgAsString value with returned one*/
} catch (Exception e) {
LOG.error(e.getMessage());
}
finally{
message.acknowledge();
}
}
return msgAsString;
}
private void tryToReconnect(String sqsServiceUrl, String queueName) throws JMSException {
String currentHour = Calendar.getInstance().get(Calendar.DAY_OF_MONTH) + "-" + Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
if (!savedHour.equals(currentHour) || (session == null || messageConsumer == null)){
synchronized(lock){
if (messageConsumer == null){
savedHour = currentHour;
SQSConnection connection = createSqsConnection(sqsServiceUrl, queueName);
session = createSqsSession(connection);
messageConsumer = createMessageReciever(connection, queueName);
}
}
}
}
I am polling the queue with the help of infinite loop, I want the code in such a way so that it picks one message at a time from queue, process it, acknowledge it and then ONLY pick the next available one.

httpClient: How to check whether the connection was already closed by the server side

We connect to a data provider and keep reading XML data in an endless loop using HttpClient. We already set connection timeout and socket timeout in the Java code. However, when the connection is closed on the HTTP server side, our application does not throw any exception and just hangs there doing nothing. Because of this behavior, when the server is up the Java code will not reconnect. Is there any way to see whether the socket connection was already closed by the server side?
In addition, https://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html mentioned how to close STALE connections, but it still does not solve our problem.
Thank you very much in advance!
Code snippet:
private static final HttpClientConnectionManager CONN_MGR = new BasicHttpClientConnectionManager();
public boolean connectToServer() {
disconnect();
CredentialsProvider provider = new BasicCredentialsProvider();
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(username, password);
provider.setCredentials(AuthScope.ANY, credentials);
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(15 * 1000)
.setSocketTimeout(15 * 1000).build();
HttpClient client = HttpClientBuilder.create().setDefaultCredentialsProvider(provider)
.setSSLSocketFactory(sslsf)
.setConnectionManager(CONN_MGR)
.setDefaultRequestConfig(requestConfig).build();
HttpGet request = new HttpGet(url);
try {
HttpResponse response = client.execute(request);
in = response.getEntity().getContent();
reader = new BufferedReader(new InputStreamReader(in));
connected = true;
return true;
} catch (Exception re) {
LOGGER.error("error", re);
}
return false;
}
public void process() {
String xml = null;
while (!shuttingDown) {
try {
/* if we know the server side closed the connection already here
we can simply return and scheduler will take care of anything else. */
xml = reader.readLine();
lastSeen = System.currentTimeMillis();
if (StringUtils.isBlank(xml)) {
continue;
}
xml = xml.trim();
// processing XML here
} catch (IOException | NullPointerException ie) {
/* We see SocketTimeoutException relatively often and
* sometimes NullPointerException in reader.readLine(). */
if (!shuttingDown) {
if(!connectToServer()) {
break;
}
}
} catch (RuntimeException re) {
LOGGER.error("other RuntimeException", re);
break;
}
}
// the scheduler will start another processing.
disconnect();
}
// called by the scheduler periodically
public boolean isConnected() {
CONN_MGR.closeExpiredConnections();
CONN_MGR.closeIdleConnections(15, TimeUnit.SECONDS);
long now = System.currentTimeMillis();
if (now - lastSeen > 15000L) {
LOGGER.info("call disconnect() from isConnected().");
disconnect();
}
return connected;
}
I think with the introduction of Automatic Resource management in java 1.7
https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
cleaning up of stale connections has been taken care and even on the worst case it has been taken care by the implementation providers carefully by monitoring the connection
Apache HttpClient uses HttpClientConnectionManager and other utility classes that does the job of cleaning the stale connections.
After the last catch block add a finally block for your cleanup code.
finally {
CONN_MGR.shutdown();
}
As per documentation it shuts down connection manager and releases allocated resources
We avoided the problem by closing the connection from another thread when no data coming in for more than 15 seconds. More specifically now isConnected() method is as follows:
// called by the scheduler periodically
public boolean isConnected() {
long now = System.currentTimeMillis();
if (now - lastSeen > 15000L) {
disconnect();
}
return connected;
}
Of course, the reading part get will java.net.SocketException: Socket closed or java.lang.IllegalStateException: Connection is still allocated when this happens.
After this change everything works fine.

Reading Data from Bluetooth Data Transfer on Android

I am looking to get/read the Data I passed after I connected a couple of Android Devices, so far I pair, connect and transmit the information between them, but not sure how to implement the reading part, here I am not sure if I should use createRfcommSocketToServiceRecord or listenUsingRfcommWithServiceRecord to create the reading socket for this purpose.
I have two screens, one where the user push a button and transmit the info and the other where the receiver press another button and read the data, I wonder if the sync is incorrect and after I push the "send" button and then the "read" button the connection is unavailable or if this implementation is just not recomendable all together.
These are my two attempts:
Attempt 1:
//Executed after the user press the read data button
private void connectToServerSocket(BluetoothDevice device, UUID uuid) {
try{
BluetoothServerSocket serverSocket = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(device.getName(),uuid);
//Here is where I get the error:
//io to Server Socket JSR82 Connection is not created, failed or aborted
BluetoothSocket clientSocket = serverSocket.accept();
// Start listening for messages.
StringBuilder incoming = new StringBuilder();
listenForMessages(clientSocket, incoming);
// Add a reference to the socket used to send messages.
transferSocket = clientSocket;
} catch (IOException ioe) {
this.printToast("Excep io toServerSocket:" + ioe.getMessage());
} catch (Exception e) {
this.printToast("Excep toServerSocket:" + e.getMessage());
}
}
Attempt 2:
private void connectToServerSocket(BluetoothDevice device, UUID uuid) {
try{
BluetoothServerSocket clientSocket = device.createRfcommSocketToServiceRecord(uuid);
//clientSocket without method and invoke is not working either
Method m = device.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
clientSocket = (BluetoothSocket) m.invoke(device, 1);
//Here is where I get the error:
//io to Server Socket JSR82 Connection is not created, failed or aborted
clientSocket.connect();
// Start listening for messages.
StringBuilder incoming = new StringBuilder();
listenForMessages(clientSocket, incoming);
// Add a reference to the socket used to send messages.
transferSocket = clientSocket;
} catch (IOException ioe) {
this.printToast("Excep io toServerSocket:" + ioe.getMessage());
} catch (Exception e) {
this.printToast("Excep toServerSocket:" + e.getMessage());
}
}
On serverSocket.accept() or clientSocket.connect() I get the exception:
Connection is not created, failed or aborted
I would appreciate if anyone could guide me towards getting the data reading part working. Thanks.
Take a look at Android's BluetoothChat example included with the Android SDK. I think it does exactly what you want.
$ANDROID_SDK/samples/android-19/legacy/BluetoothChat/src/com/example/android/BluetoothChat
Read the managing the connection part.
Its clearly written in the documentation how to exchange (read/write) info between devices through Bluetooth. http://developer.android.com/guide/topics/connectivity/bluetooth.html

ActiveMQ Queue And consumers

I am having a scenerio that , i am having more than 4 clients and i want to send a single queue messages to all of that clients. I didnt acknowledge for the client side. So anyone can get that messages from the queue. But the case is that i want to know the number of consumers who consumed that message. Can anyone help me to get the consumer count.
Here below is code that i wrote.
public static boolean sendMessage(String messageText)
{
try {
StompConnection connection = new StompConnection();
HashMap<String, String> header = new HashMap<String, String>();
header.put(PERSISTENT, "true");
connection.open(URLhost, port);
connection.connect("", "");
connection.begin("MQClient");
Thread.sleep(100);
connection.send(queuePath, messageText, "MQClient", header);
connection.commit("MQClient");
connection.disconnect();
return true;
} catch (Exception e) {
throw new BasicException(AppLocal.getIntString("ActiveMQ service ERROR"), e);
}
}
public static String receiveMessage() {
try {
StompConnection connection = new StompConnection();
connection.open(URLhost, port);
connection.connect("", "");
connection.subscribe(queuePath, Subscribe.AckModeValues.INDIVIDUAL);
connection.begin("MQClient");
Thread.sleep(1000);//below not a good NO DATA test .. worked by making thread sleep a while
if (connection.getStompSocket().getInputStream().available() > 1)
{
StompFrame message = connection.receive();
connection.commit("MQClient");
connection.disconnect();
return message.getBody();
}
else
return "";
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
If you are writing to a Queue, then exactly one consumer will receive the message. The whole goal of point-to-point messaging is that only one of the consumers will receive the message.
If you want to send a message and have it be received by all of the consumers, then you'd want to use a Topic instead of a Queue.
If you switch to a topic, multiple clients can consume that same message.
You can probably figure out how many consumed your message by subscribing to the ActiveMQ.Advisory.MessageConsumed.Topic

Detect if connection is failed - Java Android

How to check if server is online or offline, and if is offline start connecting until server is on. I have tried with this:
connectBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new Thread(rConnection).start();
}
});
public Runnable rConnection = new Runnable() {
#Override
public void run() {
boolean status = connect();
while (!status)
{
System.out.println("Connection Status: " + status);
status = Connect();
}
}
};
public boolean Connect() {
boolean status = false;
try {
s = new Socket(SERVER_ADDRESS, TCP_SERVER_PORT);
System.out.println("Socket: " + s.toString());
if (s.toString() != "")
{
status = true;
}
} catch (UnknownHostException e) {
e.printStackTrace();
status = false;
s=null;
} catch (IOException e) {
e.printStackTrace();
status = false;
s=null;
} catch (NullPointerException e)
{
e.printStackTrace();
status = false;
s=null;
}
return status;
}
If server is running before staring app it connects successfully but if server is off or disconnects after some time I don't get any error message and it won't start reconnecting again. How to solve this?
Basically you may split this:
s = new Socket(SERVER_ADDRESS, TCP_SERVER_PORT);
into
s = new Socket();
s.connect(remoteAddr,timeout)
And then control if connect returns on timeout or on successfull connection.
Look at this thread for a solution and keywords: How can I monitor the network connection status in Android? . Also, consider retrying requests on a new connection if the underlying connection is lost (or times out).
How to check if server is online or offline, and if is offline start connecting until server is on
Try to connect to it when you need to connect to it, and handle the failures that result. At present you seem to be trying to maintain an eternal connection, which is never going to work. The best way to detect whether a resource is available is to try to use it at the time that you need to use it. Anything is subject to numerous sources of error such as timing window problems, testing the wrong thing, testing the right thing at the wrong time, and at best to overuse of scarce resources. Rethink your requirement.

Categories

Resources