I have a client that serializes a class to a stream, which goes through a socket, to my server.
So i send this object to my server, where my server would save the ''object'' by doing:
object readObject = formatter.Deserialize(stream);
It fails to deserialize saying:
Unable to find assembly etc. etc.
Does this mean there is no way for my server to take the object, push it through a few more sockets to other clients, where the clients deserialize it? Does the server really require the original class in order to deserialize to an object?
I do not want my server to be able to open all these objects at all, i just want it to serve was a broadcaster to all my active clients.
Help is appreciated,
Smiley
Assuming that you have the source code to the client and server, you could extract the class definition for the object into a separate class library project (DLL) and then reference it from both the client application and the server application. That way, both of them have knowledge of the class and deserialization should work fine.
For example code look at TCPMessageServer available open source from codeplex
https://tcpmessageserver.codeplex.com/
Related
Hi StackOverflow Members,
I have created an HTTP server using WebsocketsharpAPI https://github.com/sta/websocket-sharp.
Here I have created an HTTP address = "http://localhost:0001/MoviePage";
I am then, Initializing and creating the Httpserver and starting it under the
Subquery /MoviePage . Here to test if client is receiving data in first place, I am sending a string of movie name instead of movie object that I have
Server.WebSocketServices[DisplayCollimationPort].Sessions.Broadcast("Spider Man 2");
The Server works without any issue. However, the issue is - I am not sure, How to use this
Websocketsharp API to Create a client and receive the sent string via a broadcast function from the server.
The examples are given only harnessing(or maybe I am missing something) the Websocketserver and Websocket class for the Server and Client in the examples provides.
Now since my address is an HTTP one and not a (ws or wss) (WebSocket) one, I would like to know if I can still use this websocketsharp API to implement a client to fetch string sent in this URL and access it. This is also because I would not be able to receive the information from httpserver with Websocket class.
Any suggestions would be much appreciated.
Thanks in Advance !!
I am maintaining a legacy module where the system gets some information from the user (asp.net) and then calls a remote server via remoting to print a receipt on a printer connected to the remote server. Until recently, the remote server was able to connect to the database, so we passed only a int value (the paymentId).
But now, our main application (asp.net) is being moved offsite along with the database, but the receipt printing still has to work, so now, we are trying to send all the receipt's information so the server can generate the receipt from that instead of using the id and generating the receipt from the database. So, the concept is pretty basic, except... remoting is a bit of a pain sometimes. ;)
My object is serializable and inherits from MarshalByRefObject. It contains some int, decimal and string properties. The object goes through and seems to be serialized and deserialized correctly, but when any property is called, I receive the exception. I have read on other posts/forums that I must open a client channel on my client application (asp.net), but I'm confused.
My client application connects to many such remoting services depending on the printer it must print on. Must I create a client channel for each one? can I configure a client channel "on demand" when I connect to the server or must I create it at the app start? Can I specify when I connect (Activator.GetObject(...)) to use a bidirectional channel? Is there a way not to need the client channel (as in transform all properties to fields or something)?
Here is my stack trace (so we see the problem is the PaymentID property, which is the first one that is accessed) :
at System.Runtime.Remoting.Proxies.RemotingProxy.InternalInvoke(IMethodCallMessage reqMcmMsg, Boolean useDispatchMessage, Int32 callType)
at System.Runtime.Remoting.Proxies.RemotingProxy.Invoke(IMessage reqMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at GDCMLib.Reports.DataSources.PaymentReceiptItem.get_PaymentID()
at GDCMLib.Services.PaymentReceiptPrintRemoteObj.PaymentReceiptPrint.PrintPaymentReceipt(PaymentReceiptItem paymentReceipt) in u:\SVNClient\PortailDCM\trunk\Libraries\GDCMLib.Services.PaymentReceiptPrintRemoteObj\PaymentReceiptPrint.cs:ligne 37
Finally, as my data structure only used basic data types, I made sure it was transferred as a value type by changing it from a class to a struct. It now works perfectly.
I have two queries here :-
1) What is the basic difference between Microsoft.ServiceModel.Web.RequestInterceptor and System.ServiceModel.Dispatcher.DispatchRuntime.MessageInspectors (IdispatchMessageInterceptor)
Both appears to be Request/Message interceptors which can be used to implement custom validation/interceptors in the request pipeline.
When to use one on another?
2) Also how to plugin RequestInterceptor in RouteTable.Routes.Add(new ServiceRoute())
I have class like this -
public class AuthenticationInterceptor : RequestInterceptor
{
//Authentication logic goes here......
}
and a route definition like this : -
RouteTable.Routes.Add(new ServiceRoute(routePrefix, new MyServiceHostFactory(container, (sh) => {
foreach (System.ServiceModel.Dispatcher.ChannelDispatcher cd in sh.ChannelDispatchers)
{
foreach (System.ServiceModel.Dispatcher.EndpointDispatcher ed in cd.Endpoints)
{
ed.DispatchRuntime.MessageInspectors.Add(new AuthenticationInterceptor());
}
}
return sh; })));
Here is the definition of MyServiceHostFactory: -
public MyServiceHostFactory(IocContainer container, Func<ServiceHost, ServiceHost> createservicehost = null);
Now it is throwing following error : -
The best overloaded method match for 'System.Collections.Generic.SynchronizedCollection<System.ServiceModel.Dispatcher.IDispatchMessageInspector>.Add(System.ServiceModel.Dispatcher.IDispatchMessageInspector)' has some invalid arguments
at this line : -
ed.DispatchRuntime.MessageInspectors.Add(new AuthenticationInterceptor());
I know why, it is just because I am trying to hookup RequestInterceptor in MessageInspector. Both comes in different interface hierarchy.
So what should I do here?
Edit:
Also note, I cannot change AuthenticationInterceptor logic as the code in not under my control.
Here are the answers to your questions(you need to read through point number 2 to understand Interceptors and Inspectors a little):
1. Solution to the Error (you need to add your code logic to it )
Implement IDispatchMessageInspector in the following code. Please note that the name of the following class should change to inspector, but as you have mentioned you cannot change it so you should implement the interface here. Otherwise, it is recommended to create another class with Matching Inspector suffix and implementation.
public class AuthenticationInterceptor : RequestInterceptor, IDispatchMessageInspector
{
//Authentication logic goes here......
object IDispatchMessageInspector.AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
{
//Your code here.
}
void IDispatchMessageInspector.BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
//Your code here.
}
}
2. Difference between RequestInterceptor and MessageInspectors
In any client server communication there can be two important phases of communication. First, when a client establishes connection with the server and second when they both communicate.
When establishing the connection it is not necessary that the client which is trying to establish the connection is a valid client. It could be an unauthorized request as well or it could be possible that the request is valid but not intended to the destined server and requires authorization or connection rerouting.
A good example of rerouting is when :
you want regional client/servers to avoid cross region communications but one of the client(which is valid) but tries to connect to a different region server.
You want the servers selectively decide if you wish to allow cross region client-server communications for a few exceptional users.
There could be even more complex rerouting scenarios which is out of scope of this answer.
So in WCF, the Rest starter kit provides you additional ability to intercept the request during connection establishment phase. The interceptor (in your case the AuthenticationInterceptor) should authenticate such requests and if the request is invalid, it can log the necessary entries and just reject to process any communication further from this rejected client/session.
We have many benefits of having a RequestInterceptor:
It helps us to validate the incoming request at a very early phase.
It can help us to build custom authenticators or rerouting components.
It blocks any further message processing during request phase itself which is very important to keep the unnecessary load away from the WCF Service/Server.
Message Inspectors:
The MessageInspectors can be treated as part of second phase of client-server communication when a Request is validated and connection is well established and thus it's the time when client-server has to started communicating by passing messages to each other. Now, in your application environment it could be possible that the messages pass using a binary, xml or json serialized format. There could be applicable encryptions.
An example is, it is possible that a message arrives from client A and given to Server B now server Queues it up to another Server C which can wait for some more information from Another Server D. Once Server D provides the information, the Server C which has the message in queue further joins the raw message received from Server B and Server D, gives it to another service to deserialize and convert it to something meaningful which can be returned to server B and B returns it back to Client A.
Quite complex, right? But a multi server authentication like payments by credit card using mobile PIN somewhat works in similar manner, though could be not exactly the same, but even more complex.
In WCF, Interceptors and Inspectors can work together and their duties are different. An interceptor validates the end user/connection/rerouting and an Inspector validates/processes the message.
A few points:
You can build your own message inspectors by implementing IClientMessageInspector for the client side and IDispatchMessageInspector on the server side.
You can implement both of the interfaces in a single class if you are owner of both client and server components.
Here, in your case it seems you need to implement IDispatchMessageInspector.
A class implementing IDispatchMessageInspector does not intercepts as I mentioned before but is meant to 'Inspect' an incoming message and any outgoing message and this Inspector can be hooked using configurations when a message arrives from the client.
Please note that by this time at Inspector levels, any message which arrives is already processed at various channel stack levels and assigned to which WCF Service will process this request. If you are using any encryption in between, then the message has already been decrypted. But, the message is not deserialized yet.
A use of having your custom Inspector is it could be possible that your system implements custom serialization format like (SWIFT/FIX protocol in banking) or another level of zip/unzip encoding etc.
This custom inspector can deserialized the data and give it to your component COMP which is actually meant to work on the deserialized data.
An IDispatchMessageInspector interface has got two methods which you need to implement:
a) AfterReceiveRequest and
b) BeforeSendReply(ref Message, Object).
AfterReceiveRequest is the method which can dezerialize the data and gives it to COMP, and BeforeSendReply is the method which again serializes the data and perform any operation on the message.
You can use behaviors to attach the MessageInspectors for every message your web service receives.
Both, custom Interceptors and Inspectors are largely meant to be used in Enterprise Platform or a Highly customizable platforms.
Hope this answer helps you. You can read more on the following links (possible you have gone through the first one):
http://msdn.microsoft.com/en-us/library/ee391967.aspx
http://msdn.microsoft.com/en-us/library/aa717047(v=vs.110).aspx
Regards
Kajal
I never saw someone commenting this. How should I program when using sockets?
For example, comparing web service and sockets, using web services I can create methods with a clarified name. How can I do this using sockets? What if I want to have "methods" in different classes? How do I organize them?
I am trying to make a game. What if I need to have 300 methods and I need to use sockets?
What about this?
udpClient.Connect("localhost", 15000);
Byte[] sendBytes = Encoding.ASCII.GetBytes("MyClass MyMethod(firstParameter");
udpClient.Send(sendBytes, sendBytes.Length);
I need to pass a string to an UDP communication. How can I organize this in the server side?
How can I split in classes and methods? Or do I need to put 300 "if" in the server side like this?
if(message.Contains("MyClass MyMethod"))
{
MyClass.MyMethod();
}
if(message.Contains("MyClass MyMethod2"))
...
if(message.Contains("MyClass MyMethod3"))
...
Web services like you're talking about tend to have a few layers between the actual data being received and the method that you've provided. For example:
Client sends message
Server receives message
Server translates message into something usable
Server provides usable message to web service method
In your case, you are wanting to emulate the same kind of functionality with a direct socket connection and no web service framework to do the heavy lifting for you, so you need to provide 2, 3, and 4 yourself.
It would help if you had a standard way of structuring your data so that you can provide information to the server, such as "Which method do you want to call?", and frankly, you can do it however you want. It's your client/server, you could use SOAP, JSON, you could even create your own fixed-length field format, as long as both sides speak in terms of the same data structure.
If you have specific implementation questions about a particular path you are going down, however, you are welcome to ask a different question.
Given that my client code knows everything it needs to about the remoting object, what's the simplest way to connect to it?
This is what I'm doing at the moment:
ChannelServices.RegisterChannel(new HttpChannel(), false);
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(IRemoteServer), "RemoteServer.rem", WellKnownObjectMode.Singleton);
MyServerObject = (IRemoteServer)Activator.GetObject(
typeof(IRemoteServer),
String.Format("tcp://{0}:{1}/RemoteServer.rem", server, port));
The first two lines are in the server-side code, for marshaling out the server object, yes?
In that case, yes, the third line is the simplest you can get at client-side.
In addition, you can serve out additional server-side objects from the MyServerObject instance, if you include public accessors for them in IRemoteServer interface, so, accessing those objects become the simple matter of method calls or property accesses on your main server object, so you don't have to use activator for every single thing:
//obtain another marshalbyref object of the type ISessionManager:
ISessionManager = MyServerObject.GetSessionManager();
WCF.
I have used IPC before there was a WCF, and believe me, IPC is a bear. And it isn't documented fully/correctly.
What’s the simplest way to connect to a .NET remote server object? WCF.