DataWriter StoreAsync() throws exception - websocket

I got an issue as part of remote websocket server accessing ('ws://172.17.35.104:8080/WebsocketHttpListenerDemo') from UWP app.
DataWriter StoreAsync() throws exception . A method was called at an unexpected time. (Exception from HRESULT: 0x8000000E)
please refer the below sample code (client):
private async void Button_Click(object sender, RoutedEventArgs e)
{
Connect("ws://172.17.35.104:8080/WebsocketHttpListenerDemo").Wait();
}
public async Task Connect(string uri)
{
await Task.Delay(100); //wait for a sec, so server starts and ready to accept
// await Task.Delay(TimeSpan.FromSeconds(1));
messageWebSocket = new Windows.Networking.Sockets.MessageWebSocket();
messageWebSocket.Control.MessageType = Windows.Networking.Sockets.SocketMessageType.Utf8;
messageWebSocket.MessageReceived += WebSocket_MessageReceived;
messageWebSocket.Closed += WebSocket_Closed;
try{
Task connectTask = messageWebSocket.ConnectAsync(new Uri(uri)).AsTask();
await connectTask.ContinueWith(_ => this.SendMessageUsingMessageWebSocketAsync("Hello, World!"));
await Task.Delay(1000);
}
catch (Exception ex)
{}
finally
{ }
}
private async Task SendMessageUsingMessageWebSocketAsync(string message)
{
try
{
using (var dataWriter = new DataWriter(this.messageWebSocket.OutputStream))
{
dataWriter.WriteString(message);
await dataWriter.StoreAsync();
dataWriter.DetachStream();
}
}
catch (Exception ex)
{}
}
server side code:
WebsocketServer websocketServer = new WebsocketServer();
websocketServer.Start("http://172.17.35.104:8080/WebsocketHttpListenerDemo/");
------------
public async void Start(string httpListenerPrefix)
{
HttpListener httpListener = new HttpListener();
httpListener.Prefixes.Add(httpListenerPrefix);
httpListener.Start();
Console.WriteLine("Listening...");
while (true){
HttpListenerContext httpListenerContext = await httpListener.GetContextAsync();
ProcessRequest(httpListenerContext);
}
}
private async void ProcessRequest(HttpListenerContext httpListenerContext)
{
WebSocketContext webSocketContext = await httpListenerContext.AcceptWebSocketAsync(subProtocol: null);
WebSocket webSocket = webSocketContext.WebSocket;
byte[] receiveBuffer = new byte[1024];
while (webSocket.State == WebSocketState.Open)
{
WebSocketReceiveResult receiveResult = await webSocket.ReceiveAsync(new ArraySegment<byte>(receiveBuffer),
CancellationToken.None);
}
}

Please refer the Official WebSocket sample and look into the Run the sample part in the sample README.md file to Configure your web server.
I tried to use the sample provided web server scripts and connect to the "ws://localhost/WebSocketSample/EchoWebSocket.ashx" server address to test your above code, it can work well. You can also try the Official WebSocket sample or the sample localhost server.

Related

How to implement HttpClient in Xamarin.Forms applications using better CPU and Memory?

I am bit confused about all those problems and workarounds of httpclient usage in xamarin.forms. I would like to summarize my understanding and hesitations/questions
Disposing every time vs Singleton HttpClient and Static Client: It is said that dont use using around httpClient and use singleton implementation as stated in this article
Wrong;
var httpClient = new HttpClient(new HttpClientHandler
{
//Some settings
});
Correct:
public class HttpService
{
private readonly HttpClient _httpClient;
public HttpService()
{
_httpClient = CreateHttpClient();
}
Here the first question, if we dont use static what is the advantage of this?
Because HttpService will start a new client for each thread, not? If we use static client, will this cause any memory cycle?
Xamarin forms is very fragile about static dependency, if you are holding a static value inside a ViewModel and ViewModel is coupled with View using Freshmvvm, Prism etc., usually View wont be disposed and instance remains in the memory and causes memory leak even after popping the page.
DNS changes problem: it looks like that there is a problem to use singleton HttpClient whenever DNs changes as described here. How to overcome this problem in a xamarin.forms application? I dont see any ServicePointManager defined in .net standard 2.0. Do I really have to worry about this?
ReadAsStreamAsync vs ReadAsStringAsync when getting response. Does it make a big difference to use ReadAsStreamAsync? and is there any side effect to use as stream?
Should we dispose HttpResponseMessage with a using like below?
using (HttpResponseMessage response = await client.GetAsync(uri))
{
if (!response.IsSuccessStatusCode)
{
//Do something
}
else
{
//Do something
}
}
Finally my Class looks like as below; Do you see any problem with this?
proxy setting are described in this article
namespace myApp
{
public class HttpService
{
private readonly HttpClient client;
private JsonSerializer _serializer = new JsonSerializer();
public HttpService()
{
if (client == null)
{
try
{
HttpClientHandler handler = new HttpClientHandler
{
Proxy = Xamarin.Forms.DependencyService.Get<IProxyInfoProvider>().GetProxySettings()
};
client = new HttpClient(handler);
}
catch (Exception ex)
{
}
}
}
public async Task<T> GetItemAsync<T>(string url, CancellationToken cancellationToken=default(CancellationToken))
{
T returnObject = default(T);
Uri uri = new Uri(url);
try
{
using (HttpResponseMessage response = await client.GetAsync(uri,cancellationToken))
{
if (!response.IsSuccessStatusCode)
{
//Handle error
}
else
{
returnObject = await getReturnObject<T>(response);
}
}
}
catch (OperationCanceledException)
{
}
catch (System.Net.Http.HttpRequestException)
{
}
catch (Exception ex)
{
}
return returnObject;
}
public async Task<T> getReturnObject<T>(HttpResponseMessage response)
{
T returnObject = default(T);
if (response.IsSuccessStatusCode)
{
using (System.IO.Stream stream = await response.Content.ReadAsStreamAsync())
using (System.IO.StreamReader reader = new System.IO.StreamReader(stream))
using (JsonTextReader json = new JsonTextReader(reader))
{
returnObject = _serializer.Deserialize<T>(json);
}
//string content = await response.Content.ReadAsStringAsync();
//returnObject = JsonConvert.DeserializeObject<T>(content);
}
return returnObject;
}
}
}

Endpoint is not connected in httpclient5-beta

Hi I m trying to use httpcomponents5 beta to make persistent connection, I have tried the example given in their site, the code is as follows,
final IOReactorConfig ioReactorConfig = IOReactorConfig.custom().setSoTimeout(Timeout.ofSeconds(45)).setSelectInterval(10000).setSoReuseAddress(true).setSoKeepAlive(true).build();
final SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(new TrustAllStrategy()).build();
final PoolingAsyncClientConnectionManager connectionManager = PoolingAsyncClientConnectionManagerBuilder.create().setConnectionTimeToLive(TimeValue.of(1, TimeUnit.DAYS)).setTlsStrategy(new H2TlsStrategy(sslContext, NoopHostnameVerifier.INSTANCE)).build();
client = HttpAsyncClients.createMinimal(protocol, H2Config.DEFAULT, null, ioReactorConfig, connectionManager);
client.start();
final org.apache.hc.core5.http.HttpHost target = new org.apache.hc.core5.http.HttpHost("localhost", 8000, "https");
Future<AsyncClientEndpoint> leaseFuture = client.lease(target, null);
AsyncClientEndpoint asyncClientEndpoint = leaseFuture.get(60, TimeUnit.SECONDS);
final CountDownLatch latch = new CountDownLatch(1);
final AsyncRequestProducer requestProducer = AsyncRequestBuilder.post(target.getSchemeName()+"://"+target.getHostName()+":"+target.getPort()+locationposturl).addParameter(new BasicNameValuePair("info", requestData)).setEntity(new StringAsyncEntityProducer("json post data will go here", ContentType.APPLICATION_JSON)).setHeader("Pragma", "no-cache").setHeader("from", "http5").setHeader("Custom", customheaderName).setHeader("Secure", secureHeader).build();
locEndPoint.execute(requestProducer, SimpleResponseConsumer.create(), new FutureCallback<SimpleHttpResponse>() {
#Override
public void completed(final SimpleHttpResponse response) {
if (response != null) {
if (response.getCode() > -1) {
try {
System.out.println("http5:: COMPLETED : RESPONSE "+response.getBodyText());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
latch.countDown();
}
#Override
public void failed(final Exception ex) {
System.out.println("http5:: FAILED : "+target+locationposturl);
LoggerUtil.printStackTrace(ex);
System.out.println("http5::Exception Request failed "+LoggerUtil.getStackTrace(ex));
latch.countDown();
}
#Override
public void cancelled() {
System.out.println("http5:: CANCELLED : "+target+locationposturl);
System.out.println(http5::Exception Request cancelled");
latch.countDown();
}
});
latch.await();
This code works without a problem for the first time,but when I send a subsequent requests it throws an exception as follows,
http5:: Exception occured java.lang.IllegalStateException: Endpoint is
not connected at
org.apache.hc.core5.util.Asserts.check(Asserts.java:38) at
org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager$InternalConnectionEndpoint.getValidatedPoolEntry(PoolingAsyncClientConnectionManager.java:497)
at
org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager$InternalConnectionEndpoint.execute(PoolingAsyncClientConnectionManager.java:552)
at
org.apache.hc.client5.http.impl.async.MinimalHttpAsyncClient$InternalAsyncClientEndpoint.execute(MinimalHttpAsyncClient.java:405)
at
org.apache.hc.core5.http.nio.AsyncClientEndpoint.execute(AsyncClientEndpoint.java:81)
at
org.apache.hc.core5.http.nio.AsyncClientEndpoint.execute(AsyncClientEndpoint.java:114)
What may be the problem with endpoint, I m forcing endpoint to keep alive for a day, kindly shed some light on this

Tryus websocket client - onMessage does not get called although connection is succesful

I am successfully connecting to a local websocket server with tyrus, but the onMessage method does not get called. I setup Fiddler as proxy in between and I see that the server responds with two messages, however, they are not printed out in my code. I more or less adapted the sampe code:
The onOpen Message is printed out
public static void createAndConnect(String channel) {
CountDownLatch messageLatch;
try {
messageLatch = new CountDownLatch(1);
final ClientEndpointConfig cec = ClientEndpointConfig.Builder.create().build();
ClientManager client = ClientManager.createClient();
client.connectToServer(new Endpoint() {
#Override
public void onOpen(Session session, EndpointConfig config) {
System.out.println("On Open and is Open " + session.isOpen());
session.addMessageHandler((Whole<String>) message -> {
System.out.println("Received message: " + message);
messageLatch.countDown();
});
}
}, cec, new URI("ws://192.168.1.248/socket.io/1/websocket/" + channel));
messageLatch.await(5, TimeUnit.SECONDS); //I also tried increasing timeout to 30sec, doesn't help
} catch (Exception e) {
e.printStackTrace();
}
}
That's a known issue - it will work if you rewrite lambda to anonymous class or use Session#addMessageHandler(Class, MessageHandler) (you can use lambdas here).

Windows Mobile 6.5 client socket send fails after first success

I am currently building a client app with a forms UI for a scanner device running Windows Mobile 6.5.
The client app needs to communicate via TCP async sockets with a console server app.
Server and client built using the following info:
Server & Client.
My dev/test environment is as follows:
Console server app running on windows 7 desktop.
The cradled device is connected via USB and Windows Mobile Device Center.
The mobile client app manages to connect to the server, send the message and receive a response back initially.
However when I try and send another message (new socket), the app fails. The new socket doesn't seem to be connected the second time around?
I get the following exception:
NullReferenceException
at
SocketClient.ReceiveCallback()at System.Net.LazyAsyncresult.InvokeCallback()
at
WorkerThread.doWork()...
Code follows:
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text;
using System.Collections.Generic;
using System.Windows.Forms;
namespace SeatScan
{
static class Program
{
public static string serverIP;
public static int serverPort;
public static string response;
public static string message = string.Empty;
/// <summary>
/// The main entry point for the application.
/// </summary>
[MTAThread]
static void Main()
{
serverIP = MobileConfiguration.Settings["ServerIP"];
serverPort = int.Parse(MobileConfiguration.Settings["ServerPort"]);
Application.Run(new frmLogin());
}
public static void SendMessage(string message)
{
SocketClient.StartClient(serverIP, serverPort, message);
response = SocketClient.response;
}
}
static class SocketClient
{
// ManualResetEvent instances signal completion.
private static ManualResetEvent connectDone = new ManualResetEvent(false);
private static ManualResetEvent sendDone = new ManualResetEvent(false);
private static ManualResetEvent receiveDone = new ManualResetEvent(false);
// The response from the remote device.
public static string response = String.Empty;
public static void StartClient(string serverIP, int serverPort, string message)
{
response = String.Empty;
// Connect to a remote device.
try
{
// Establish the remote endpoint for the socket.
IPAddress ipAddress = IPAddress.Parse(serverIP);
IPEndPoint remoteEP = new IPEndPoint(ipAddress, serverPort);
// Create a TCP/IP socket.
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//socket.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.DontLinger, false);
//socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
// Connect to the remote endpoint.
socket.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), socket);
connectDone.WaitOne();
MessageBox.Show("connect=" + socket.Connected, "Connecting?");
// Send test data to the remote device.
Send(socket, message);
sendDone.WaitOne();
// Receive the response from the remote device.
Receive(socket);
receiveDone.WaitOne();
// Release the socket.
socket.Shutdown(SocketShutdown.Both);
socket.Close();
socket = null;
}
catch (Exception e)
{
//response = e.Message;
//Console.WriteLine(e.ToString());
MessageBox.Show(e.Message.ToString(), "StartClient");
}
}
private static void ConnectCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete the connection.
client.EndConnect(ar);
//Console.WriteLine("Socket connected to {0}", client.RemoteEndPoint.ToString());
//MessageBox.Show("Socket connected to {0}", client.RemoteEndPoint.ToString());
// Signal that the connection has been made.
connectDone.Set();
}
catch (Exception e)
{
//Console.WriteLine(e.ToString());
MessageBox.Show(e.Message.ToString(), "ConnectCallback");
}
}
private static void Receive(Socket client)
{
try
{
// Create the state object.
StateObject state = new StateObject();
state.workSocket = client;
// Begin receiving the data from the remote device.
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
catch (Exception e)
{
//Console.WriteLine(e.ToString());
MessageBox.Show(e.Message.ToString(), "Receive");
}
}
private static void ReceiveCallback(IAsyncResult ar)
{
try
{
// Retrieve the state object and the client socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.workSocket;
// Read data from the remote device.
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
// Get the rest of the data.
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
else
{
// All the data has arrived; put it in response.
if (state.sb.Length > 1)
{
response = state.sb.ToString();
}
// Signal that all bytes have been received.
receiveDone.Set();
}
}
catch (Exception e)
{
//Console.WriteLine(e.ToString());
MessageBox.Show(e.Message.ToString() + e.InnerException.Message, "ReceiveCallback");
}
}
private static void Send(Socket client, String data)
{
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
client.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), client);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = client.EndSend(ar);
//Console.WriteLine("Sent {0} bytes to server.", bytesSent);
// Signal that all bytes have been sent.
sendDone.Set();
}
catch (Exception e)
{
//Console.WriteLine(e.ToString());
MessageBox.Show(e.Message.ToString() + e.InnerException.Message, "SendCallback");
}
}
}
// State object for reading client data asynchronously
public class StateObject
{
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 1024;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
}
Any help is appreciated.
Nevermind, I found the solution :)
This will teach me to copy paste sample code without fully understanding it.
It turns out, since I am reconnecting after first connect, I need to reset the state of the ManualResetEvents... Duh.
I needed to add:
connectDone.Reset();
sendDone.Reset();
receiveDone.Reset();
just before the line...
socket.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), socket);
I hope this helps someone as I lost a bit of hair figuring this one out...

How An ISO server can support concurrent requests?

I had implemented ISO SERVER by using ASCII channel and ASCII packager and listening on a port and giving response to ISO requests.
how can i make my server that accepts concurrent requests and send the response.
Please
if you are using Q2, just deploy QServer and set the minSessions and maxSessions which its default value is 0 and 100.
here example jPOS server that handle concurent request:
http://didikhari.web.id/java/jpos-client-receive-response-specific-port/
ISOServer works with a threadpool, so you can accept concurrent requests out of the box. Every socket connection is handled by its own thread. So, I think all you have to do is assign a ISORequestListener to your ISOServer to actually process your incoming messages.
Here's a test program taken from the jPOS guide:
public class Test implements ISORequestListener {
public Test () {
super();
}
public boolean process (ISOSource source, ISOMsg m) {
try {
m.setResponseMTI ();
m.set (39, "00");
source.send (m);
} catch (ISOException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
public static void main (String[] args) throws Exception {
Logger logger = new Logger ();
logger.addListener (new SimpleLogListener (System.out));
ServerChannel channel = new XMLChannel (new XMLPackager());
((LogSource)channel).setLogger (logger, "channel");
ISOServer server = new ISOServer (8000, channel, null);
server.setLogger (logger, "server");
server.addISORequestListener (new Test ());
new Thread (server).start ();
}
}

Resources