Similar to other ping questions here, we need to ping many IP addresses at the same time. We thought we had it running great after following many responses and examples from here, however we are experiencing failed pings due to timeout when we attempt to ping them at the same time, or even close together.
We tested our list of IP's on another ping monitoring program and the timeout does not happen. The issue is specific to our application.
In our application, every "device" has a RouterProperties class that holds its Name, IP Address, etc. We ping from the observable collection of these devices, getting their IP addresses from their RouterProperties.
Tested separating pings by 10(ms)/20(ms) await task.delay
Tested separating pings by 10(ms)/20(ms) using a dispatcher timer
Tested pinging all at once with no delay between, causing largest amounts of timeouts.
Tested converting IP Address "strings" to IP Address before pinging, no visible change in issue.
Tested with ping timeout at 500(ms), 1000(ms), 5000(ms), etc.
Current test is for 143 devices, but needs to be able to handle more.
//OUR MAIN PING SCHEDULER
private async void PingAllDevices(object sender, EventArgs e)
{
var allPingTasks = new List<Task>();
int numOfDevices = 1;
//Assign a task to each device.
foreach (RouterProperties device in devices)
{
await Task.Delay(10);
Console.WriteLine("Pinging device #" + numOfDevices + " : " + device.RouterIP);
numOfDevices++;
allPingTasks.Add(AsyncPingDevice(device));
}
//Block here for all created tasks.
await Task.WhenAll(allPingTasks);
}
}
//OUR PING TASK
async Task AsyncPingDevice(RouterProperties device)
{
// Get device IP address to ping.
string deviceIP = device.RouterIP;
try
{
Ping pingSender = new Ping();
PingOptions options = new PingOptions();
var reply = await pingSender.SendPingAsync(deviceIP, (int.Parse(Properties.Settings.Default.PingTimeout)), buffer, pingOptions);
Console.WriteLine(deviceIP + " has responded.");
if (reply.Status == IPStatus.Success)
{
device.PingCounter = 0;
}
else
{
if (device.PingCounter <= 3)
{
device.PingCounter++;
}
}
}
catch
{
if (device.PingCounter <= 3)
{
device.PingCounter++;
}
}
await Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action( () =>
{
if (device.IsDeactivated != true)
{
switch (device.PingCounter)
{
case 0:
device.Color = "#FF8AA587";
break;
case 1:
device.Color = "#FF9AB999";
break;
case 2:
device.Color = "#FFFCCEAA";
break;
case 3:
device.Color = "#FFF4837D";
break;
case 4:
device.Color = "#FFEB4960";
break;
}
}
}));
}
When we run our code, with and without the task.delay inside the ping scheduler to separate the pings, we end up with inconsistent results from the devices being pinged.
Without the delay = 75% of all devices timeout.
With the delay = inconsistently random 10% of devices timing out per
cycle.
Similar ping program to ours = 100% consistent results without any
timeouts.
Related
I'm trying to resolve a problem with the search bar. It works but the problem is that if I press two keys almost at the same time, the app will only search the words with the first key pressed.
Here are the logs:
In this one, it works when I press the P then R:
[EDT] 0:4:9,283 - p
[EDT] 0:4:9,348 - 10
[EDT] 0:4:9,660 - pr
[EDT] 0:4:9,722 - 3
The second one doesn't because I press P and R nearly at the same time:
[EDT] 0:4:35,237 - p
[EDT] 0:4:35,269 - pr
[EDT] 0:4:35,347 - 0
[EDT] 0:4:35,347 - 10
The logs here are generated to show the String searched and the result size. As you can see, the first case get results before typing the next char and the second case got all results when the two chars are typed.
The main problem is that in the second case, results from the 'p' String are shown instead of those of 'pr'.
I'm using the searchbar from the Toolbar API with addSearchCommand and an InfiniteContainer to show result data.
Could it be a problem in the order of the events from the addSearchCommand are treated ?
EDIT: Here is the client side code. Server side it's just a simple rest service call which fetch the data from the database.
public static ArrayList<Patient>getSearchedPatient(int index,int amount, String word)
{
ArrayList<Patient> listPatient = null;
Response reponse;
try {
reponse = RestManager.executeRequest(
Rest.get(server + "/patients/search")
.queryParam("index", String.valueOf(index))
.queryParam("amount", String.valueOf(amount))
.queryParam("word", word),
RequestResult.ENTITIES_LIST,
Patient.class);
listPatient = (ArrayList<Patient>)reponse.getResponseData();
Log.p(""+listPatient.size());
} catch (RestManagerException e) {
LogError("", e);
}
return listPatient;
}
private static Response executeRequest(RequestBuilder req, RequestResult type, Class objectClass) throws RestManagerException
{
Response response = null;
try {
switch (type) {
case BYTES:
response = req.getAsBytes();
break;
case JSON_MAP:
response = req.acceptJson().getAsJsonMap();
break;
case ENTITY:
response = req.acceptJson().getAsProperties(objectClass);
break;
case ENTITIES_LIST:
response = req.acceptJson().getAsPropertyList(objectClass);
break;
default:
case STRING:
response = req.getAsString();
break;
}
} catch (Exception e) {
log().error("Erreur à l'exécution de la requête", e);
response = null;
}
if(response == null)
return null;
return response;
}
So the trick here is a simple one. Don't make a request... Most users type fast enough to saturate your network connection speed so you will see completion suggestions referring to things that are no longer relevant.
This is a non-trivial implementation which I discuss in-depth in the Uber book where such a feature is implemented.
The solution is to send a request after a delay while caching responses to avoid double requests and ideally canceling request in progress when applicable. The solution in the Uber book does all 3 I'll try to cover just the basics in this mockup code. First you need a field for the timer and current request. Ideally you would also have a Map containing cached data:
private UITimer delayedRequest;
private String currentSearch;
private Map<String, String> searchCache = new HashMap<>();
Then you need to bind a listener like this:
tb.addSearchCommand(e -> {
String s = (String)e.getSource();
if(s == null) {
if(delayedRequest != null) {
delayedRequest.cancel();
delayedRequest = null;
}
return;
}
if(currentSearch != null && s.equals(currentSearch)) {
return;
}
if(delayedRequest != null) {
delayedRequest.cancel();
delayedRequest = null;
}
currenSearch = s;
delayedRequest = UITimer.timer(100, false, () -> {
doSearchCode();
});
});
I didn't include here usage of the cache which you need to check within the search method and fill up in the result code. I also didn't implement canceling requests already in progress.
I used this link to send SMS with AT command in WPF.
But when I send SMS with CMGS command, the receiver get the SMS as Flash SMS not usual SMS. My code is as below:
//Check if modem allows you to send and receive SMS messages using AT commands, without the need to decode the binairy PDU field of the SMS first
rval = sp.SendCommand("AT+CMGF=1");
//set Text mode parameters
rval = sp.SendCommand("AT+CSMP=17,167,0,16");
string phonenumber = "xxxxxxxxxxx";
string Message = "test";
rval = sp.SendCommand("AT+CMGS=\"" + phonenumber + "\"");
if (rval.Equals("\r\n> "))
{
rval = sp.SendCommand(Message + char.ConvertFromUtf32(26) );
}
and my SendCommand is as below
public string SendCommand(String commandText)
{
if (!serialPort.IsOpen)
{
try
{
serialPort.Open();
}
catch (Exception ex)
{
LogEvents.InLogFile(ex.Message);
throw new Exception("COM port is busy");
}
}
try
{
serialPort.DiscardOutBuffer();
serialPort.DiscardInBuffer();
buff = "";
serialPort.Write(commandText + "\r");
Thread.Sleep(serialPort.ReadTimeout);
return buff;
}
catch (Exception)
{
throw new Exception("Error connection");
}
}
Can any one help me?
My other references:
developershome,
Sayeda Anila Nusrat
The fourth parameter in AT+CSMP sets the coding scheme, i don't remember in which document i've found the coding of this byte but bit 7 sets whether the message should be discarded after showing it class 0 or stored
You should set this bit to 1 to make it storable, so changing
rval = sp.SendCommand("AT+CSMP=17,167,0,16");
to
rval = sp.SendCommand("AT+CSMP=17,167,0,144");
should do the work
Bit 0 (i.e., the least significant bit) of the fourth parameter of the AT+CSMP command is a flag for whether the SMS will be flashed (when 0) or saved (when 1).
Simply put: An even number for 4th parameter will NOT save the message, while an odd number will.
Change AT+CSMP=17,167,0,16 to AT+CSMP=17,167,0,0.
I have a weird case that I need to create many processes from my main process.
These processes that I create will queue some messages from a web socket.
And in an interval, like every second or so, I will poll these small processes from my main process. The language I use is D and the messaging library is ZMQD ( which is just a wrapper for C zmq library ).
The minimal example I have for my main process :
Socket*[] socketList;
string sRecv( Socket* socket)
{
ubyte[256] buffer;
immutable size = socket.receive(buffer);
import std.algorithm: min;
return buffer[0 .. min(size,256)].idup.asString();
}
void startServer( string servername )
{
auto pid = spawnProcess(["/home/erdem/eclipse-workspace/WebSocketDenemesi/websocketdenemesi",
servername, "\n"]);
auto requester = new Socket(SocketType.req);
auto allName = "ipc:///tmp/" ~ servername;
requester.connect(allName);
socketList ~= requester;
}
void main() {
import std.array : split;
import std.algorithm : each;
startServer("iotabtc#depth");
startServer("iotabtc#aggTrade");
startServer("ethbtc#depth");
int counter = 30;
while(counter--) {
foreach ( requester; socketList)
{
requester.send("send");
}
foreach ( requester; socketList)
{
auto strList = sRecv(requester).split("\n");
strList.each!( str => writefln("Received [%d]reply [%s]", strList.length, str) );
}
sleep(1000.msecs);
}
foreach ( requester; socketList)
{
requester.send("done");
}
}
And the minimal example I have for my small processes :
WebSocket startSocket( string temp )
{
auto ws_url = URL(temp);
auto ws = connectWebSocket(ws_url);
if ( !ws.connected )
return null;
return ws;
}
void close( WebSocket ws )
{
int timeOut = 5;
while ( ws && ws.connected && timeOut-- )
{
vibe.core.concurrency.async( { ws.close(); return true;} );
sleep(5.msecs);
}
}
string sRecv(ref Socket socket)
{
ubyte[256] buffer;
immutable size = socket.tryReceive(buffer)[0];
import std.algorithm: min;
return size ? buffer[0 .. min(size,256)].idup.asString() : "";
}
void main( string[] args ) {
auto responder = Socket(SocketType.rep);
string seperatorChar = args[2];
string temp = "ipc:///tmp/" ~ args[1];
responder.bind(temp);
string socketName = "wss://stream.binance.com:9443/ws/" ~ args[1];
auto curSocket = startSocket(socketName);
string curString;
while (true) {
auto result = responder.sRecv();
if ( result == "send")
{
responder.send(curString);
curString = "";
}
else if ( result == "done" )
{
break;
}
else
{
if ( curSocket.dataAvailableForRead )
{
auto text = curSocket.receiveText();
if ( !curString.empty )
curString ~= seperatorChar;
curString ~= text;
}
}
sleep(100.msecs);
}
writeln( "Shutting down: ", args[1]);
curSocket.close();
}
This is the first time I am using this Messaging library. That is why I am using simple REQ/REP sockets. Is there a better way to achieve my requirement. Is there a better messaging pattern for example? For example is there a pattern in which my small processes are not blocked by responder.receive( buffer );.
If there is some, than I will not need to listen websocket from another thread.
Welcome to the ZeroMQ-based distributed-computing
Is there a better messaging pattern for example ?
This depends on how your processes need to communicate. In short, using REQ/REP in a blocking-mode is almost the worst option from the menu.
given your websocket just receives an async piece of information ( which is a common way, how Markets re-broadcast the flow of events ), the pure ws.recv() + PUSHer.send() + if PULLer.poll(): PULLer.recv() pipelined event-acquisition + PUSH/PULL propagation + conditional re-processing would best meet the real-world behaviour.
given your footprint of processing farm may grow beyond a single localhost, other transport-classes, for non-local nodes ~{ tipc:// | tcp:// | udp:// | pgm:// | epgm:// | norm:// | vmci:// } might get into the game, altogether with ipc://-links on your current localhost - ZeroMQ transparency in handling this mix is a cool benefit of moving into mastering the Zen-of-Zero.
given latency is critical on a massive scale of processing distribution, a PUB/SUB Scalable Formal Communication Archetype Pattern may become beneficial, with an option to use .setsockopt( zmq.CONFLATE, 1 ) for non-logging nodes, where just the most recent prices are relevant for taking any responsive XTO action of any sort of kind.
Is Hazelcast always blocking in case initial.min.cluster.size is not reached? If not, under which situations is it not?
Details:
I use the following code to initialize hazelcast:
Config cfg = new Config();
cfg.setProperty("hazelcast.initial.min.cluster.size",Integer.
toString(minimumInitialMembersInHazelCluster)); //2 in this case
cfg.getGroupConfig().setName(clusterName);
NetworkConfig network = cfg.getNetworkConfig();
JoinConfig join = network.getJoin();
join.getMulticastConfig().setEnabled(false);
join.getTcpIpConfig().addMember("192.168.0.1").addMember("192.168.0.2").
addMember("192.168.0.3").addMember("192.168.0.4").
addMember("192.168.0.5").addMember("192.168.0.6").
addMember("192.168.0.7").setRequiredMember(null).setEnabled(true);
network.getInterfaces().setEnabled(true).addInterface("192.168.0.*");
join.getMulticastConfig().setMulticastTimeoutSeconds(MCSOCK_TIMEOUT/100);
hazelInst = Hazelcast.newHazelcastInstance(cfg);
distrDischargedTTGs = hazelInst.getList(clusterName);
and get log messages like
debug: starting Hazel pullExternal from Hazelcluster with 1 members.
Does that definitely mean there was another member that has joined and left already? It does not look like that would be the case from the log files of the other instance. Hence I wonder whether there are situtations where hazelInst = Hazelcast.newHazelcastInstance(cfg); does not block even though it is the only instance in the hazelcast cluster.
The newHazelcastInstance blocks till the clusters has the required number of members.
See the code below for how it is implemented:
private static void awaitMinimalClusterSize(HazelcastInstanceImpl hazelcastInstance, Node node, boolean firstMember)
throws InterruptedException {
final int initialMinClusterSize = node.groupProperties.INITIAL_MIN_CLUSTER_SIZE.getInteger();
while (node.getClusterService().getSize() < initialMinClusterSize) {
try {
hazelcastInstance.logger.info("HazelcastInstance waiting for cluster size of " + initialMinClusterSize);
//noinspection BusyWait
Thread.sleep(TimeUnit.SECONDS.toMillis(1));
} catch (InterruptedException ignored) {
}
}
if (initialMinClusterSize > 1) {
if (firstMember) {
node.partitionService.firstArrangement();
} else {
Thread.sleep(TimeUnit.SECONDS.toMillis(3));
}
hazelcastInstance.logger.info("HazelcastInstance starting after waiting for cluster size of "
+ initialMinClusterSize);
}
}
If you set the logging on debug then perhaps you can see better what is happening. Member joining and leaving should already be visible under info.
What i wanna do is this; I want to run the processing code below, and after 2 minutes it should stop automatically and make itself run again and after 2 min stop again and again. I mean I don't want to run the code by clicking run button manually.
I'm so beginner on processing, I would be so glad if you can answer I desperately need this.
import processing.serial.*;
// The serial port:
Serial myPort;
String dataReading = "";
String [] dataOutput = {};
void setup() {
size(500,500);
// Open the port you are using at the rate you want:
myPort = new Serial(this, Serial.list()[7], 9600);
//in my case,the Serial port the Arduino is connected to is 9th on the serial list, hence the [8]
//to get access to the serial list you can use >> println(Serial.list());
myPort.bufferUntil('\n');
}
void draw() {
//...
}
void serialEvent(Serial myPort) {
dataReading = myPort.readString();
if(dataReading!=null){
dataOutput = append(dataOutput, dataReading);
saveData();
}
}
void saveData() {
println("saving to txt file...");
saveStrings("data/data.txt", dataOutput);
}