I have the UWP app("server") running on win10 prof, this UWP app is an application service and I have another UWP app(Client), which communicates with that service using TSP/IP. How many clients running on the other win10 devices can connect to the "server" at the same time?
Using the StreamSocketListener class, I believe you can handle an unlimited number of client socket connections (depending on implementation, hardware, bandwidth, etc.). Here's a basic example of the server-side implementation of the listener using a static class.
// Define static class here.
public static StreamSocketListener Listener { get; set; }
// This is the static method used to start listening for connections.
public static async Task<bool> StartServer()
{
Listener = new StreamSocketListener();
// Removes binding first in case it was already bound previously.
Listener.ConnectionReceived -= Listener_ConnectionReceived;
Listener.ConnectionReceived += Listener_ConnectionReceived;
try
{
await Listener.BindServiceNameAsync(VMS.Current.Port);
return true;
}
catch (Exception ex)
{
Listener.ConnectionReceived -= Listener_ConnectionReceived;
Listener.Dispose();
return false;
}
}
private static async void Listener_ConnectionReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
{
var remoteAddress = args.Socket.Information.RemoteAddress.ToString();
var reader = new DataReader(args.Socket.InputStream);
var writer = new DataWriter(args.Socket.OutputStream);
try
{
// Handle communication here. You'll likely use an infinite loop of reading from the input stream until the socket is disconnected.
}
catch (Exception ex)
{
writer.DetachStream();
reader.DetachStream();
return;
}
}
There are different ways of handling stream sockets once you have both ends connected, and I had to do some research and experimentation to find a process that worked for what I was doing.
Related
I could create a server lease to a single client as follows:
#Slf4j
public class LeaseServer {
private static final String SERVER_TAG = "server";
public static void main(String[] args) throws InterruptedException {
// Queue for incoming messages represented as Flux
// Imagine that every fireAndForget that is pushed is processed by a worker
int queueCapacity = 50;
BlockingQueue<String> messagesQueue = new ArrayBlockingQueue<>(queueCapacity);
// emulating a worker that process data from the queue
Thread workerThread =
new Thread(
() -> {
try {
while (!Thread.currentThread().isInterrupted()) {
String message = messagesQueue.take();
System.out.println("consume message:" + message);
Thread.sleep(100000); // emulating processing
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
});
workerThread.start();
CloseableChannel server = getFireAndForgetServer(messagesQueue, workerThread);
TimeUnit.MINUTES.sleep(10);
server.dispose();
}
private static CloseableChannel getFireAndForgetServer(BlockingQueue<String> messagesQueue, Thread workerThread) {
CloseableChannel server =
RSocketServer.create((setup, sendingSocket) ->
Mono.just(new RSocket() {
#Override
public Mono<Void> fireAndForget(Payload payload) {
// add element. if overflows errors and terminates execution
// specifically to show that lease can limit rate of fnf requests in
// that example
try {
if (!messagesQueue.offer(payload.getDataUtf8())) {
System.out.println("Queue has been overflowed. Terminating execution");
sendingSocket.dispose();
workerThread.interrupt();
}
} finally {
payload.release();
}
return Mono.empty();
}
}))
.lease(() -> Leases.create().sender(new LeaseCalculator(SERVER_TAG, messagesQueue)))
.bindNow(TcpServerTransport.create("localhost", 7000));
return server;
}
}
But how do I issue a lease to multiple clients connected to that server?
Otherwise my queue will be written multiple times by multiple clients, resulting in an overflow of the service.
I can't find the details in the public documents and materials.
Your help was very much appreciated.
I'm using Cucumber to test my service when it is deployed to a container. The request contains a URL the service calls when the operation is successful. What is a good way to create a Cucumber test that waits for the Http callback? The Gherkin script would look something like.
Scenario: Process Order
Given An Order has been submitted
When the Order is processed
Then the order process service calls back with a successful status message
What would the Java glue code look like?
Here's the solution I came up with using an embedded http server. In the OrderSteps.java glue code I added a class used to start the server on another thread.
private static class Callback implements Runnable
{
public void run()
{
HttpServer server;
try
{
server = HttpServer.create(new InetSocketAddress(8000), 0);
server.createContext("/callback", new CallbackHandler());
server.setExecutor(null); // creates a default executor
server.start();
}
catch (IOException e)
{
logger.debug("HTTP server loop failure.", e);
}
}
static class CallbackHandler implements HttpHandler
{
#Override
public void handle(HttpExchange t) throws IOException
{
// Read the message and set the global variable
// which informs the main test thread a callback
// has been received.
InputStream is=t.getRequestBody();
byte[] buf=new byte[1000];
int len=is.read(buf);
OrderSteps.receivedCallback=new String(buf,0,len);
String response = "Callback received.";
t.sendResponseHeaders(200, response.length());
// Send response
OutputStream os = t.getResponseBody();
os.write(response.getBytes());
os.close();
}
}
}
Then in the OrderSteps class, in the step/method that publishes the Order, the server thread is started and then the order is submitted. This guarantees the server will receive the callback, since it is listening before the order is submitted.
// Start a listener for the callback.
Thread callbackThread = new Thread(new Callback());
callbackThread.start();
In the step/method that checks if the callback was received, there's a loop checking the static variable to see if it has been set.
// Allow 5 seconds for the callback to occur.
for (int i = 0; i < 5; i++)
{
if (receivedCallback != null) {
break;
}
Thread.sleep(1000);
}
if (receivedCallback == null) fail("Callback was not received.");
assertEquals("Expected callback message", receivedCallback);
I am confused with Async feature introduced in Servlet 3.0 spec
From Oracle site (http://docs.oracle.com/javaee/7/tutorial/doc/servlets012.htm):
To create scalable web applications, you must ensure that no threads
associated with a request are sitting idle, so the container can use
them to process new requests.
There are two common scenarios in which a thread associated with a
request can be sitting idle.
1- The thread needs to wait for a resource to become available or process data before building the response. For example, an application
may need to query a database or access data from a remote web service
before generating the response.
2- The thread needs to wait for an event before generating the response. For example, an application may have to wait for a JMS
message, new information from another client, or new data available in
a queue before generating the response.
The first item happens a lot (nearly always, we always query db or call a remote webservice to get some data). And calling an external resource will always consume some time.
Does it mean that we should ALWAYS use servelt async feature for ALL our servelts and filter ?!
I can ask this way too, if I write all my servelts and filters async, will I lose anything (performance)?!
If above is correct the skeleton of ALL our servlets will be:
public class Work implements ServletContextListener {
private static final BlockingQueue queue = new LinkedBlockingQueue();
private volatile Thread thread;
#Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
thread = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
ServiceFecade.doBusiness();
AsyncContext context;
while ((context = queue.poll()) != null) {
try {
ServletResponse response = context.getResponse();
PrintWriter out = response.getWriter();
out.printf("Bussiness done");
out.flush();
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
} finally {
context.complete();
}
}
} catch (InterruptedException e) {
return;
}
}
}
});
thread.start();
}
public static void add(AsyncContext c) {
queue.add(c);
}
#Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
thread.interrupt();
}
}
I have the code for using HttpClient below but now I want to use Windows Azure Mobiles Services.. My app was not published because they said I am not checking for a connection.. What is a simple way to do this ?
private void StackPanel_Loaded(object sender, RoutedEventArgs e)
{
SystemTray.ProgressIndicator = new ProgressIndicator();
//try to ping service before getting high scores
try
{
SetProgressIndicator(true);
SystemTray.ProgressIndicator.Text = "Loading...";
GetHighScores(); //?????????
// HttpClient httpClient = new HttpClient();
// HttpResponseMessage response = await httpClient.GetAsync("http://punkoutersoftware.azurewebsites.net/api/drunkmeterscore");
// response.EnsureSuccessStatusCode();
SetProgressIndicator(false);
}
catch (HttpRequestException e)
{
MessageBox.Show("High Scores not available at the moment");
}
}
private async void GetHighScores()
{
try
{
scores = await scoreTable.OrderByDescending(x => x.Score).ToCollectionAsync();
}
catch (MobileServiceInvalidOperationException e)
{
MessageBox.Show(e.Message, "Error loading items", MessageBoxButton.OK);
}
ListItems.ItemsSource = scores;
}
I doubt the verification process tests with an unresponsive Azure Mobile Services. They're likely testing with no data connection. You can check for a data connection before doing any operation that might need a data connection like this:
if(!DeviceNetworkInformation.IsNetworkAvailable)
{
// inform user to get a data connection
}
I am creating a j2me application which is interacting with a database on a server. Therefore I launch a thread to connect to the server. I handle all my command actions in a separate class which implements CommandListener.
When I try to get the response the server returned I get an empty String. I have tried waiting for the thread that connects to the server to return but this makes the application unresponsive.
Below is the code I am using.
//my network worker class.
public class NetworkConnector implements Runnable {
//constructor
public NetworkConnector(String url){
//url =>server url to connect to.
Thread thread = new Thread(this);
thread.start();
}
private String serverReply="";
private String url="
//method to connect to the server and return the
//response from the server.
public String sendData(String serverUrl) {
//open streams to connect to the Server.
httpConn = (HttpConnection)
Connector.open(serverUrl,Connector.READ_WRITE, true);
httpConn.setRequestMethod(HttpConnection.GET);
inStream = httpConn.openInputStream();
int read;
while ((read = inStream.read()) != -1) {
sb.append((char) read);
}
return sb.toString();
}
public String getServerReply() {
//serverReply is a class variable.
return serverReply;
}
public void run(){
//call the send method that connects to the server.
serverResponse = sendData(Url);
}
} //end of connector class.
// this class is where all my Command Actions are
//implemented.
public class CommandActionController implements
CommandListener, DataReceiver {
public void commandAction(Command cmd, Displayable d) {
//networkMgr => is the worker class that makes
//connection to the server.
networkMgr = new NetworkConnector("http://localhost
/JsonPhp/login.php?uname=" + loginUserInfo.userName +
"&passwd=" + loginUserInfo.password);
//here am getting the response from the server.
String serverResponse = networkMgr.getServerReply();
//at this point the ServerReponse String is Empty =>
//yet the server is supposed to return some String.
System.out.println("xxxxxxxxxxxxxxxxxx
ServerResponse =" + serverResponse);
}
}//end of CommandListener class.
Your expectations about serverResponse value are wrong; it can be empty at the moment when you attempt to obtain it in commandAction with the code snippet in the question.
In order to get non-empty value, you need to redesign method NetworkConnector.getServerReply() to make it properly wait until thread finishes and server response is indeed obtained.
If you do that, however, you will also have to redesign CommandActionController to keep user interface responsive - your testing with "waiting for the thread that connects to the server" has shown just that.
Redesigned code should just launch the server connect thread and exit the commandAction as soon as possible (possibly changing to some "wait screen" to let user see what happens). Next screen update should be triggered only after server response is obtained.
Consider studying a tutorial specifically targeted on explaining how to properly design this kind applications - Networking, User Experience, and Threads:
This article explains how your MIDlet can make network connections without compromising your user interface. It includes six iterative examples that illustrate multithreaded networking and the use of a wait screen...
Here is how I'd do without java.util.concurrent:
Result handleRequest(){
final String url = // get url
Work work = new Work(url):
Thread t = new Thread(work);
t.start();
// do other stuff
if(t.isAlive()){
// still running
}
// this waits until the work is done
// and it will be safe to access work.result after
// this call has returned.
t.join();
return work.result;
}
and then
class Work implements Runnable{
final String url;
Result result;
public void run(){
this.result = // do your network stuff
}
}
You shouldn't start a thread in the constructor. Also, runnable are meant to be passed to threads. The easiest (and the "proper") way of doing this would be as follows:
Implement a Callable instead of a Runnable.
Use a ExecutorService instead of a Thread
Use Future object to do the processing asynchronously/be responsive to user
Here is a simple example.
class Stuff {
final ExecutorService exec =
Executors.newCachedExecutorService(// please see doc);
Result process(String url){
Future<Result> future = exec.submit(new Work(url));
// do some other stuff
if(future.isDone()){
// return result?
}
return future.get(); // this call will wait until result is available
}
}
and then
class Work implements Callable<Result> {
final String url;
Result call() throws Exception {
// do your network stuff here
return result;
}
}
See documentation of java.util.concurrent.ExecutorService.submit(), java.util.concurrent.Future and java.util.concurrent.Callable for details.