TCP/IP Client in Kotlin that does not wait forever for server message - kotlin

I have simple TCP/IP client code in Kotlin below.
This code works.
The client opens the socket and loops forever, first sending a message to the server, and then waiting forever for a response form the server.
I know this code isn’t great, looping forever, keeping the socket connection open etc., but it is just for test purposes right now.
fun tcp_client() {
thread {
val client1 = Socket(SERVER_IP_ADDRESS, SERVER_IP_PORT)
val output1 = PrintWriter(client1.getOutputStream(), true)
val input1 = BufferedReader(InputStreamReader(client1.inputStream))
while (true) {
output1.println(str_user_text)
str_rcvd_data = input1.readLine()
}
}
client1.close()
}
The line:
str_rcvd_data = input1.readLine()
waits forever for a server response.
My question: Is it possible to modify this code so that the client does NOT wait forvever for a server response? Something like this:
If (server data received) {
// process the data
} else {
// do something else for now and check again in a short while
}
Thanks in advance for any suggestions
Garrett

I eventually worked this out - I am not sure how 'correct' this solution is, but it works for me:
Connecting to the server....
My old code would hang if it couldn't connect, because the call to Socket() with the IP address and Port is a Blocking call - i.e.e wait forever:
val client1 = Socket(SERVER_IP_ADDRESS, SERVER_IP_PORT)
So I replaced the code with this:
try {
client1 = Socket()
client1.connect(InetSocketAddress(SERVER_IP_ADDRESS, SERVER_IP_PORT), 3000)
output1 = DataOutputStream (client1.getOutputStream())
input1 = DataInputStream (client1.getInputStream())
} catch (ex : Exception) {
// do something
} finally {
// do something
}
This isn't perfect, but it works.
For reading the data, my old code called readline() which is blocking:
str_rcvd_data = input1.readLine()
Now, my code first checks if there is any data and then grabs each byte
iRxDataAvailable = input1.available()
while (iRxDataAvailable > 0)
{
iRxDataAvailable--
// Take a copy of the received byte
byRcvdByte = input1.readByte()
// Do something with this data byte...
}
Finally, to send data to the server, the data is placed in a byte array, and then:
output1.write(byArray)

Related

ktor websocket listener for new message

Is there a way to run some code each time a ktor websocket receives a new message, kind of like onTouchEvent in Android views?
Currently I check for new messages and process them in a while loop as follows:
while (websocketIsOpen) {
val newMessage = session!!.incoming.receive()
processMessage(newMessage)
}
where session is a DefaultClientWebsocketSession?, and processMessage is a method that has a Frame as a parameter.
I would prefer to set code that runs each time a new message is received, something like the following:
session!!.incoming.onNewMessage = { newMessage ->
processMessage(newMessage)
}
You can use consumeEach method of the incoming frames channel to run some code when a frame is received:
webSocket("/") {
incoming.consumeEach { frame ->
if (frame is Frame.Text) {
println("They say ${frame.readText()}")
}
}
}

How can I get a non-blocking infinite loop in a Kotlin Actor?

I would like to consume some stream-data using Kotlin actors
I was thinking to put my consumer inside an actor, while it polls in an infinite loop while(true). Then, when I decide, I send a message to stop the consumer.
Currently I have this:
while(true) {
for (message in channel){ <--- blocked in here, waiting
when(message) {
is MessageStop -> consumer.close()
else -> {}
}
}
consumer.poll()
}
The problem
The problem with this is that it only runs when I send a message to the actor, so my consumer is not polling the rest of the time because channel is blocking waiting to receive the next message
Is there any alternative?, someone with the same issue?, or something similar to actors but not blocked by channel in Kotlin?
Since the channel is just a Channel (https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-channel/index.html) you can first check if the channel is empty and if so start your polling. Otherwise handle the messages.
E.g.
while(true) {
while (channel.isNotEmpty()) {
val message = channel.receive()
when(message) {
is MessageStop -> consumer.close()
else -> {}
}
}
consumer.poll()
}
In the end I used AKKA with Kotlin, I'm finding much easier this way
You should use postDelayed(), for example:
final Runnable r = new Runnable() {
public void run() {
// your code here
handler.postDelayed(this, 1000)
}
}
You can change 1000 with the the millisecond delay you want. Also I highly recommend to put your code inside a thread (if you are not already have) to prevent ANR (App Not Responding)

Winsock UDP sendto and get respond back like function?

I am try to figure out if the Winsock UDP way of sending and recieving datagrams has an option to get a respond back to the sendto() like a function.
To make it clear lets say that i have a function that uses UDP to send a message
and needs to return back a true or false state
Since this function is using UDP to send a message, the application that recieves the message needs to execute a specific command and send back the returned value of true false to the UDP sender, so in that way the function from the control program will know that the function was properly executed or not.
Application 1 :
bool Test(){
functionToRun = "checkandRespond";
respond = sendto(....);
if(respond == "true"){
Brespond = true;
}else{
Brespond = false;
}
return Brespond;
}
Application 2 :
bool check(){
return true;
}
DWORD WINAPI IncomingMessages(){
recvfrom(....)
//run the function requested e.x.
bool respondto1App = check();
sendback the respondto1App boolean to string to Application 1
}
Is there any way to get back an instant respond like a function needs between two applications using UDP ?
NOTE : i don`t want to know if the sendto() command has send the message to the other application successfully, i want to get the respond back from the second application like if i was running the check() function from application 1.
Thanks in advance for any help on the issue

How to make an Attended call transfer with UCMA

I'm struggling with making a call transfer in a UMCA IVR app I've built. This is not using Lync.
Essentially, I have an established call from an outside user and as part of the IVR application, they select an option to be transferred. This transfer is to a configured outside number (ie: Our Live Operator). What I want to do is transfer the original caller to the outside number, and if a valid transfer is established, I want to terminate the original call. If the transfer isn't established, I want to send control back to the IVR application to handle this gracefully.
My problem is my EndTransferCall doesn't get hit when the transfer is established. I would have expected it to hit, set my AutoResetEvent and return a True, and then in my application I can disconnect the original call. Can somebody tell me what I'm missing here?
_call is an established AudioVideoCall. My application calls the Transfer method
private AutoResetEvent _waitForTransferComplete = new AutoResetEvent(false);
public override bool Transfer(string number, int retries = 3)
{
var success = false;
var attempt = 0;
CallTransferOptions transferOptions = new CallTransferOptions(CallTransferType.Attended);
while ((attempt < retries) && (success == false))
{
try
{
attempt++;
_call.BeginTransfer(number, transferOptions, EndTransferCall, null);
// Wait for the transfer to complete
_waitForTransferComplete.WaitOne();
success = true;
}
catch (Exception)
{
//TODO: Log that the transfer failed
//TODO: Find out what exceptions get thrown and catch the specific ones
}
}
return success;
}
private void EndTransferCall(IAsyncResult ar)
{
try
{
_call.EndTransfer(ar);
}
catch (OperationFailureException opFailEx)
{
Console.WriteLine(opFailEx.ToString());
}
catch (RealTimeException realTimeEx)
{
Console.WriteLine(realTimeEx.ToString());
}
finally
{
_waitForTransferComplete.Set();
}
}
Is the behavior the same if you don't use the _waitForTransferComplete object? You shouldn't need it - it should be fine that the method ends, the event will still be raised. If you're forcing synchronous behavoir in order to fit in with the rest of the application though, try it like this:
_call.EndTransfer(
_call.BeginTransfer (number,transferOptions,null,null)
);
I'm just wondering if the waiting like that causes a problem if running on a single thread or something...

How can a RabbitMQ Client tell when it loses connection to the server?

If I'm connected to RabbitMQ and listening for events using an EventingBasicConsumer, how can I tell if I've been disconnected from the server?
I know there is a Shutdown event, but it doesn't fire if I unplug my network cable to simulate a failure.
I've also tried the ModelShutdown event, and CallbackException on the model but none seem to work.
EDIT-----
The one I marked as the answer is correct, but it was only part of the solution for me. There is also HeartBeat functionality built into RabbitMQ. The server specifies it in the configuration file. It defaults to 10 minutes but of course you can change that.
The client can also request a different interval for the heartbeat by setting the RequestedHeartbeat value on the ConnectionFactory instance.
I'm guessing that you're using the C# library? (but even so I think the others have a similar event).
You can do the following:
public class MyRabbitConsumer
{
private IConnection connection;
public void Connect()
{
connection = CreateAndOpenConnection();
connection.ConnectionShutdown += connection_ConnectionShutdown;
}
public IConnection CreateAndOpenConnection() { ... }
private void connection_ConnectionShutdown(IConnection connection, ShutdownEventArgs reason)
{
}
}
This is an example of it, but the marked answer is what lead me to this.
var factory = new ConnectionFactory
{
HostName = "MY_HOST_NAME",
UserName = "USERNAME",
Password = "PASSWORD",
RequestedHeartbeat = 30
};
using (var connection = factory.CreateConnection())
{
connection.ConnectionShutdown += (o, e) =>
{
//handle disconnect
};
using (var model = connection.CreateModel())
{
model.ExchangeDeclare(EXCHANGE_NAME, "topic");
var queueName = model.QueueDeclare();
model.QueueBind(queueName, EXCHANGE_NAME, "#");
var consumer = new QueueingBasicConsumer(model);
model.BasicConsume(queueName, true, consumer);
while (!stop)
{
BasicDeliverEventArgs args;
consumer.Queue.Dequeue(5000, out args);
if (stop) return;
if (args == null) continue;
if (args.Body.Length == 0) continue;
Task.Factory.StartNew(() =>
{
//Do work here on different thread then this one
}, TaskCreationOptions.PreferFairness);
}
}
}
A few things to note about this.
I'm using # for the topic. This grabs everything. Usually you want to limit by a topic.
I'm setting a variable called "stop" to determine when the process should end. You'll notice the loop runs forever until that variable is true.
The Dequeue waits 5 seconds then leaves without getting data if there is no new message. This is to ensure we listen for that stop variable and actually quit at some point. Change the value to your liking.
When a message comes in I spawn the handling code on a new thread. The current thread is being reserved for just listening to the rabbitmq messages and if a handler takes too long to process I don't want it slowing down the other messages. You may or may not need this depending on your implementation. Be careful however writing the code to handle the messages. If it takes a minute to run and your getting messages at sub-second times you will run out of memory or at least into severe performance issues.