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
Related
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)
I'm currently working on creating tests for specific use cases one of which is Init WF200 -> connect to AP -> send TCP data -> Deinit WF200. The application is very energy critical so I have to ensure that the WF200 is enabled as short as possible.
The hardware I use is a EFM32GG11 MCU together with a WF200 WIFI transceiver, both from SiliconLabs. I'm using an RTOS and the lwip stack with the netconn API for TCP communication.
The problem is that I can't find a way to know if the TCP transaction was completed, which I need to know before putting the WF200 into shutdown. Currently the task is faster then the actual transmission which leads to data loss and incomplete TCP communication.
Currently I have a working work around which is adding a delay. But that doesn't seem like an elegant solution to me, especially because the delay is dependent on the amount of data being sent.
I have already tried checking the tcp pcb state but with no success. Is there some way I can block the thread until the transaction is completed?
Thanks in advance!
static void tcp_thread(void *p_arg) {
struct netconn *conn;
err_t err;
LWIP_UNUSED_ARG(p_arg);
// needed, otherwise netconn_connect fails
KAL_Dly(1);
conn = netconn_new(NETCONN_TCP);
if (conn != NULL) {
struct ip4_addr broker_ip;
IP_ADDR4(&broker_ip, SERVER_IP_0, SERVER_IP_1, SERVER_IP_2, SERVER_IP_3);
err = netconn_connect(conn, &broker_ip, 65432);
if (err == ERR_OK) {
// NOCOPY only safe when data is static and const
err = netconn_write(conn, test_data, strlen(test_data), NETCONN_NOCOPY);
printf("Data sent\n");
netconn_close(conn);
netconn_delete(conn);
} else {
printf("No TCP connection\n");
}
} else {
printf("No netconn\n");
}
KAL_Dly(200);
sl_wfx_deinit();
OSTaskDel(0, &err);
}
netconn will execute a call back, you can add while(1){osDelay(2);} to your code and wait for that callback to finish. Maybe post a flag in the callback you can check for. For example you can use that data RX callback (or error callback, etc), inspect for an ack, then write to a var you can check in your code's while loop.
i am new to iPhone development so i don't know whether this is simple or complicated.
Here is my problem. I have a app which first connects to web service for authentication process. After authentication i need to get data of logged in user. So, how to connect to web services twice and serially using NSURLConnection. Serially means first login and then retrieve data. In my case, the request are sent in random order, means sometime it sends login request first and some time retrieve data request.
Can anyone please help this out.
Thanks.
Set the delegate of your NSURLConnection to self, and implement NSURLConnectionDelegate methods, there's a method named
- (void) connectionDidFinishLoading:(NSURLConnection*)connection
which tells you when the request was finished successfully so inside it you can call the second request.
Now your only problem is that you don't know which request to call second :) as you don't know which one was called first so what I usually do is simply, define some variable, simply an int or NSString as a tag, e.g.
Add these before your #implemenetation
#define TAG_LOGIN_REQUEST 1
#define TAG_DATA_REQUEST 2
now define this inside the class
int currentTag
now before you start the login request add this
currentTag = TAG_LOGIN_REQUEST;
and before you start the data request add this
currentTag = TAG_DATA_REQUEST;
whenever this delegate method gets called
- (void) connectionDidFinishLoading:(NSURLConnection*)connection
you simply check
if (tag == TAG_LOGIN_REQUEST) {
// send data request
}
else if (tag == TAG_DATA_REQUEST) {
// send login request
}
I hope this helps, if there's anything that's not clear, please tell me.
Just try to synchronise you calling. Here is a example:
request for login and wait for login response
get login response and call getData()
if login response if yes, request for data.
Hope this helps.. :)
EDIT:
maintain two global flag (variable). let loginReq and dataReq are those flag.
before calling getLogin(), make loginReq = true;
in your connectinDidFinishLoading check
if(loginReq == true){
loginReq = false;
dataReq = true;
getData();
}
else if(dataReq == true){
dataReq = false;
}
Is there a way to receive multiple message using a single synchronous call ?
When I know that there are N messages( N could be a small value less than 10) in the queue, then I should be able to do something like channel.basic_get(String queue, boolean autoAck , int numberofMsg ). I don't want to make multiple requests to the server .
RabbitMQ's basic.get doesn't support multiple messages unfortunately as seen in the docs. The preferred method to retrieve multiple messages is to use basic.consume which will push the messages to the client avoiding multiple round trips. acks are asynchronous so your client won't be waiting for the server to respond. basic.consume also has the benefit of allowing RabbitMQ to redeliver the message if the client disconnects, something that basic.get cannot do. This can be turned off as well setting no-ack to true.
Setting basic.qos prefetch-count will set the number of messages to push to the client at any time. If there isn't a message waiting on the client side (which would return immediately) client libraries tend to block with an optional timeout.
You can use a QueueingConsumer implementation of Consumer interface which allows you to retrieve several messages in a single request.
QueueingConsumer queueingConsumer = new QueueingConsumer(channel);
channel.basicConsume(plugin.getQueueName(), false, queueingConsumer);
for(int i = 0; i < 10; i++){
QueueingConsumer.Delivery delivery = queueingConsumer.nextDelivery(100);//read timeout in ms
if(delivery == null){
break;
}
}
Not an elegant solution and does not solve making multiple calls but you can use the MessageCount method. For example:
bool noAck = false;
var messageCount = channel.MessageCount("hello");
BasicGetResult result = null;
if (messageCount == 0)
{
// No messages available
}
else
{
while (messageCount > 0)
{
result = channel.BasicGet("hello", noAck);
var message = Encoding.UTF8.GetString(result.Body);
//process message .....
messageCount = channel.MessageCount("hello");
}
First declare instance of QueueingBasicConsumer() wich wraps the model.
From the model execute model.BasicConsume(QueueName, false, consumer)
Then implement a loop that will loop around messages from the queue which will then processing
Next line - consumer.Queue.Dequeue() method - waiting for the message to be received from the queue.
Then convert byte array to a string and display it.
Model.BasicAck() - release message from the queue to receive next message
And then on the server side can start waiting for the next message to come through:
public string GetMessagesByQueue(string QueueName)
{
var consumer = new QueueingBasicConsumer(_model);
_model.BasicConsume(QueueName, false, consumer);
string message = string.Empty;
while (Enabled)
{
//Get next message
var deliveryArgs = (BasicDeliverEventArgs)consumer.Queue.Dequeue();
//Serialize message
message = Encoding.Default.GetString(deliveryArgs.Body);
_model.BasicAck(deliveryArgs.DeliveryTag, false);
}
return message;
}
In my test application I can see messages that were processed with an exception being automatically inserted into the default EasyNetQ_Default_Error_Queue, which is great. I can then successfully dump or requeue these messages using the Hosepipe, which also works fine, but requires dropping down to the command line and calling against both Hosepipe and the RabbitMQ API to purge the queue of retried messages.
So I'm thinking the easiest approach for my application is to simply subscribe to the error queue, so I can re-process them using the same infrastructure. But in EastNetQ, the error queue seems to be special. We need to subscribe using a proper type and routing ID, so I'm not sure what these values should be for the error queue:
bus.Subscribe<WhatShouldThisBe>("and-this", ReprocessErrorMessage);
Can I use the simple API to subscribe to the error queue, or do I need to dig into the advanced API?
If the type of my original message was TestMessage, then I'd like to be able to do something like this:
bus.Subscribe<ErrorMessage<TestMessage>>("???", ReprocessErrorMessage);
where ErrorMessage is a class provided by EasyNetQ to wrap all errors. Is this possible?
You can't use the simple API to subscribe to the error queue because it doesn't follow EasyNetQ queue type naming conventions - maybe that's something that should be fixed ;)
But the Advanced API works fine. You won't get the original message back, but it's easy to get the JSON representation which you could de-serialize yourself quite easily (using Newtonsoft.JSON). Here's an example of what your subscription code should look like:
[Test]
[Explicit("Requires a RabbitMQ server on localhost")]
public void Should_be_able_to_subscribe_to_error_messages()
{
var errorQueueName = new Conventions().ErrorQueueNamingConvention();
var queue = Queue.DeclareDurable(errorQueueName);
var autoResetEvent = new AutoResetEvent(false);
bus.Advanced.Subscribe<SystemMessages.Error>(queue, (message, info) =>
{
var error = message.Body;
Console.Out.WriteLine("error.DateTime = {0}", error.DateTime);
Console.Out.WriteLine("error.Exception = {0}", error.Exception);
Console.Out.WriteLine("error.Message = {0}", error.Message);
Console.Out.WriteLine("error.RoutingKey = {0}", error.RoutingKey);
autoResetEvent.Set();
return Task.Factory.StartNew(() => { });
});
autoResetEvent.WaitOne(1000);
}
I had to fix a small bug in the error message writing code in EasyNetQ before this worked, so please get a version >= 0.9.2.73 before trying it out. You can see the code example here
Code that works:
(I took a guess)
The screwyness with the 'foo' is because if I just pass that function HandleErrorMessage2 into the Consume call, it can't figure out that it returns a void and not a Task, so can't figure out which overload to use. (VS 2012)
Assigning to a var makes it happy.
You will want to catch the return value of the call to be able to unsubscribe by disposing the object.
Also note that Someone used a System Object name (Queue) instead of making it a EasyNetQueue or something, so you have to add the using clarification for the compiler, or fully specify it.
using Queue = EasyNetQ.Topology.Queue;
private const string QueueName = "EasyNetQ_Default_Error_Queue";
public static void Should_be_able_to_subscribe_to_error_messages(IBus bus)
{
Action <IMessage<Error>, MessageReceivedInfo> foo = HandleErrorMessage2;
IQueue queue = new Queue(QueueName,false);
bus.Advanced.Consume<Error>(queue, foo);
}
private static void HandleErrorMessage2(IMessage<Error> msg, MessageReceivedInfo info)
{
}