TCPClient in asp.net mvc application - asp.net-mvc

I have asp.net mvc app that shows varios events. All events stored in a database. But now, I have to load data from the database and remote program. This program have external service (this is simple program that listening specific TCP port and recieve a query and send xml back).
And, I wrote simple page for test that connects to external program. The code got from MSDN:
static string Connect(String server, String message)
{
try
{
// Create a TcpClient.
Int32 port = 9197;
TcpClient client = new TcpClient(server, port);
// Translate the passed message into ASCII and store it as a Byte array.
Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);
// Get a client stream for reading and writing.
// Stream stream = client.GetStream();
NetworkStream stream = client.GetStream();
// Send the message to the connected TcpServer.
stream.Write(data, 0, data.Length);
// Receive the TcpServer.response.
// Buffer to store the response bytes.
data = new Byte[256];
// String to store the response ASCII representation.
String responseData = String.Empty;
// Read the first batch of the TcpServer response bytes.
Int32 bytes = stream.Read(data, 0, data.Length);
responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
stream.Close();
client.Close();
return responseData;
}
catch (ArgumentNullException e)
{
//
}
catch (SocketException e)
{
//
}
}
This is my action:
public ActionResult GetData()
{
string query = "some query";
var response = Connect("192.168.0.1", query);
var model = ParseResponse(response);
return View(model);
}
I think this solution will reduce the perfomance.
What is best practicies to use TCPClient in ASP.NET MVC 3 app?
What you think about my code?
Any suggestions are welcome.

I think this solution will reduce the perfomance.
Well. All/most database operations are done over sockets. And you do not notice that, do you?
The most likely performance issues are:
Your server
Server location
Connection setup
The only thing I would do now is to build in checks in the client to monitor the response time and write to a log (or send an email) when the response times are too high.
Don't try to optimize performance until that happen.
Solutions for the above mentioned issues:
Refactor and optimize
Either put the server on the same lan or create a cache proxy server.
Use connection pooling instead of disconnecting the connections every time.

I think this solution will reduce the perfomance.
It's as any other remote request that your server does - an I/O intensive operation. So you could use an asynchronous controller and the asynchronous versions of the TcpClient methods. This way you won't be jeopardizing any worker threads on your server during the execution of the remote request.

Related

Spring AMQP how to access response message when connection is lost while sending using #SendTo

we have a microservice which consumes a message using #RabbitListener and persist data into database, generate a response on successful processing of message and send it using #sendTO to different queue for auditing.
When running Rabbit in HA failover, while sending response if connection is lost the message currently being processed is correctly returned to the queue but database transaction (jpa transaction in our case) is not rolled back , response is never sent.
I read from this issue(https://github.com/spring-projects/spring-amqp/issues/696) that this is "best effort 1PC" transaction synchronization; RabbitMQ does not support XA transactions. The Rabbit tx is committed after the DB tx and there is a possibility the DB tx might commit and the rabbit rolled back; you have to deal with the small possibility of duplicate messages.
But in our case when we retry request, we are treating it as duplicate message and response is never created for this request. is there a way where we can only retry sending response message in case of connection lost exceptions rather than reprocessing request again? I looked at ConditionalRejectingErrorHandler.DefaultExceptionStrategy, it has access only to original request,no way to access response lost during connection failure. Please suggest what's the best way to handle this?
our code looks like:
SpringBootApplication
#EnableJpaRepositories("com.***")
#EnableJpaAuditing
#EnableTransactionManagement
#EnableEncryptableProperties
public class PcaClinicalValidationApplication {
#RabbitListener(queues = "myqueue"
#SendTo("exchange/routingKey")
#Timed) description = "Time taken to process a request")
public Message receivemessage(HashMap<String, Object> myMap, Message requestMessage)
throws Exception {
//business logic goes here
Message message = MessageBuilder.fromMessage(requestMessage)
//add some headers
return message;
}
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory,
SimpleRabbitListenerContainerFactoryConfigurer configurer) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
configurer.configure(factory, connectionFactory);
factory.setRetryTemplate(new RetryTemplate());
factory.setReplyRecoveryCallback(ctx -> {
Message failed = SendRetryContextAccessor.getMessage(ctx);
Address replyTo = SendRetryContextAccessor.getAddress(ctx);
Throwable t = ctx.getLastThrowable();
//wrote to a file
serializer.serialize(failed);
return null;
});
return factory;
}
The listener container factory uses a RabbitTemplate in its replyTemplate property - this is used to send the reply.
You can configure a RetryTemplate into that RabbitTemplate to retry sending the reply.
When retries are exhausted, you can add a RecoveryCallback which will get the failed reply and you can save it off someplace and use it when the redelivery occurs.

How can I store and persist multiple remoting sessions in an MVC application?

Imagine a monitoring website that connects to 50 services via .net remoting and polls them to check they are working and find out what they're up to, and display it.
The page uses ajax to hit the backend and the backend then connects to each one.
Ideally, I don't want it to open a connection, do the request, close the connection, for 50 connections, on a 5 second interval (unless this is the best practice way?). So I'd like MVC to persist the connections.
I can make a ConnectionManager static singleton to handle this (not sure where?), opening and closing connections as required/idling.
You could even have a ConnectionManager handle the server status, so if multiple people load the status webpage, the results are cached.
But is there a better way, especially one that is scaleable? You could have multiple ConnectionManager classes in a webfarm scenario as they won't clash afaik (you can have multiple connections open).
ATM I am doing this in my ajax methods:
TcpChannel tcpChannel = new TcpChannel();
ChannelServices.RegisterChannel(tcpChannel, false);
Type requiredType = typeof(ICatServerMarshaller);
ICatServerMarshaller remoteObject = (ICatServerMarshaller)Activator.GetObject(requiredType,
"tcp://localhost:4567/CatServerMarshaller");
string catStatus;
try
{
catStatus = remoteObject.GetCatStatus().ToString();
}
catch (SocketException ex)
{
catStatus = "Offline";
}
finally
{
ChannelServices.UnregisterChannel(tcpChannel);
}
return Json(new { catStatus = catStatus});

Stream Reader/Writer for RTSP WinRT Client App

I have spend hours to convert an old net v2 project and to port it to WinRT in C#.
Its a RTSP client thats sending commands to a DVBservice (DVBViewer). So, at this moment, the WinForm Program has been renewed and its working prety fine. Connecting, sending and receiving commands to the server and finaly the stream to my localhost UDP port are fully working and the ts stream is fully readable via VLC and RTP protocol.
But now, i'd like to write my Metro app with this stuff. I managed to do the work and seems to be almost finish (at least the Socket and stream stuff).
But now, I'm getting stuck on a stupid problem. I CAN'T communicate with the RTSP Server.
My Stream Reader/Writer is'nt working and I've tried a lot.
The app is based on code from the Uniriotec.DV project, so for any futher info, you can find it by google.
So, here's the point I'm getting stuck:
Its the main handle, thats getting the StreamSocket with the Stream (the messages) together.
//Set input and output stream filters in the main client app
RTSPBufferedReader = new BufferedReader<Stream> (RTSPsocket);
RTSPBufferedWriter = new BufferedWriter<Stream> (RTSPsocket);
namespace RTSP.Client
{
public class BufferedReader<T> : StreamReader where T : Stream
{
private StreamSocket socket;
private T unbufferedStream;
private StreamSocket streamSocket;
public T UnbufferedStream
{
get { return unbufferedStream; }
set { unbufferedStream = value; }
}
public BufferedReader(T myStream)
: base(myStream)
{
unbufferedStream = myStream;
}
public BufferedReader(StreamSocket mySocket)
: base(new Stream(mySocket)) // <== here is the problem, saying "could'nt establish an instance of the abstract or interface class "System.IO.Stream"....
{
this.streamSocket = mySocket;
}
}
}
Do you have an idea where I did the error?
Thanks for answering,
Jo
PS: I need await writer.StoreAsync(); because the answer is send approx 10-15 sec. later, when the server is ready to thread the request and sends me SessionID and so back.
The Stream class is abstract and you cannot instantiate an abstract class directly, like you are doing with the base(new Stream(mySocket)). See here for the System.IO.Stream definition
http://msdn.microsoft.com/en-us/library/windows/apps/system.io.stream.aspx
You need to replace the Stream class with the appropriate derived class, such as DataReader. Here is an example of using a StreamSocket sample that may help:
http://code.msdn.microsoft.com/windowsapps/StreamSocket-Sample-8c573931

ASP.Net MVC & WebAPI encryption

I want to utilise some form of "simple" encryption that is reasonably secure but very low friction in terms of impact on development process.
Supposing I own both sides of the conversation in a client <> web service situation. My application is a windows phone/win8/silverlight/desktop app and the server is ASP.Net MVC or WebAPI.
In my mind, I want something as simple as:-
<security encryption="off|sometype|someothertype">
<privatekey>12345MyKey54321</privatekey>
</security>
as some form of configuration parameter on both the client and server. Additionally an authentication routine will return and store some form of public key.
Doing so will enable the 'encryption mode' and result in any http requests being encrypted & hashed in the selected manner using the provided keys. The end result being anything sniffed on the local, proxy or remote machines would not be able to view the data without the key and decryption method. On the server, data is decrypted using the same key before hitting controller actions.
Other than swapping out HttpRequest/WebClient calls for something like EncryptedHttpRequest and adding the appropriate hook on the MVC/WebAPI side of things, all other client code and controller actions would be ignorant to the fact the data was encrypted.
Am I missing something or could setup not be this simple? As far as I have searched there is nothing that offers this level of simplicity so I figure I'm missing some gaping flaw in my logic?
All you are looking for can be achieved by simply using HTTPS. Just buy a certificate (or use a self-signed certificate) and there is your encryption.
Do not re-invent the wheel.
I've done this successfully. It isn't too difficult and works well. I use it for activating a license for a product. The most important thing is that your truly control the client and server - no one can extract your private key from your code on the client.
Step 1: Create an MVC controller action method that takes no arguments:
[HttpPost] public ActionResult Activate() { ... }
Step 2: In the controller just use the HttpRequest.InputStream to get ahold of the bytes sent from the client.
var stream = this.HttpContext.Request.InputStream;
Step 3: Create a CryptoStream to deserialize.
I've included creating both encryption and decryption examples here. The sharedSecret is a byte[] of sufficient length (512 bytes) of random bytes - this is what you protect!
public CryptoStream CreateEncryptionStream(Stream writeStream)
{
TripleDESCryptoServiceProvider cryptoProvider = new TripleDESCryptoServiceProvider();
PasswordDeriveBytes derivedBytes = new PasswordDeriveBytes(this._sharedSecret, null);
CryptoStream cryptoStream = new CryptoStream(writeStream, cryptoProvider.CreateEncryptor(derivedBytes.GetBytes(16), derivedBytes.GetBytes(16)), CryptoStreamMode.Write);
return cryptoStream;
}
public CryptoStream CreateDecryptionStream(Stream readStream)
{
TripleDESCryptoServiceProvider cryptoProvider = new TripleDESCryptoServiceProvider();
PasswordDeriveBytes derivedBytes = new PasswordDeriveBytes(this._sharedSecret, null);
CryptoStream cryptoStream = new CryptoStream(readStream, cryptoProvider.CreateDecryptor(derivedBytes.GetBytes(16), derivedBytes.GetBytes(16)), CryptoStreamMode.Read);
return cryptoStream;
}
Step 4: Use your CryptoStream another stream reader to decrypt.
I use an XmlReader so that all my existing serialization code can work either in the clear (when reading/writing to disk or database on the server) or encrypted (when transmitting).
using (var reader = XmlReader.Create(decryptionStream, settings)) { ... }
Step 5: Formulate a secure response in your controller.
This is doing the reverse of Steps 1-4 to encrypt your response object. Then you just write your encrypted response to a memory stream and return it as a File result. Below, I've shown how I do this for my license response object.
var responseBytes = GetLicenseResponseBytes(licenseResponse);
return File(responseBytes, "application/octet-stream");
private byte[] GetLicenseResponseBytes(LicenseResponse licenseResponse)
{
if (licenseResponse != null)
{
using (MemoryStream memoryStream = new MemoryStream())
{
this._licenseResponseSerializer.Write(memoryStream, licenseResponse);
return memoryStream.ToArray();
}
}
return null;
}
Step 6: Implement your client request response.
You can use HttpWebRequest or the WebClient classes to formulate the request. Here's a couple of examples from the code I use.
byte[] postBytes = GetLicenseRequestBytes(licenseRequest);
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(licenseServerUrl);
request.Method = "POST";
request.ContentType = "application/octet-stream";
request.Proxy = WebRequest.DefaultWebProxy;
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(postBytes, 0, postBytes.Length);
}
return request;
private LicenseResponse ProcessHttpResponse(HttpWebResponse response)
{
if ((response.StatusCode == HttpStatusCode.OK) && response.ContentType.Contains("application/octet-stream"))
{
var stream = response.GetResponseStream();
if (stream != null)
{
var licenseResponse = this._licenseResponseSerializer.Read(stream);
return licenseResponse;
}
}
return new LicenseResponse(LicensingResult.Error);
}
Summary and Tips
Use the streams in the request/responses on the client and server to communicate binary octet-stream data
Use CryptoStream along with an encryption algorithm (consider using the strongest encryption possilbe) and a good private key to encrypt data when you serialize/deserialize it.
Make sure to check the size and format all incoming data to the client and server (avoid buffer overruns and throw exceptions early)
Protect your private key on your client using obfuscation if possible (take a look at the DeepSea obfustactor)

ASP.NET MVC 3 provide large file download to browser while server retrieves file from elsewhere

I need to provide a file-download feature where the web server retrieves the file from another source (via HTTP) and simultaneously streams it to the browser. I am guessing that using MVC's Controller.File ActionResult will not work, but I wrote a prototype like this anyway:
public ActionResult Download()
{
HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create("http://somewhere/somefile.pdf");
HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();
Stream stream = webResponse.GetResponseStream();
var mimeType = "application/pdf";
var fileName = "somefile.pdf";
return File(stream, mimeType, fileName);
}
This works fine, but there is no way to call Close() on the HttpWebResponse and Stream after the return statement. The help on the HttpWebResponse.GetResponseStream method says, "You must call either the Stream.Close or the HttpWebResponse.Close method to close the stream and release the connection for reuse. It is not necessary to call both Stream.Close and HttpWebResponse.Close, but doing so does not cause an error. Failure to close the stream will cause your application to run out of connections."
Should I create an HttpHandler and manually read bytes from the source stream and write them out to the response, along the lines of this or this? Is there another approach I'm not aware of?
While I'm not directly familiar with trying something like this, my first though was to do what you suggested in regards to reading in the stream, closing the connection, then returning the bytes as the response. Being a stream, I don't know how you can get around leaving it open for the sake of returning its contents as you do in your prototype, but then being able to close it when you're done.

Resources