Reputation: 231
I'm trying to send an arbitrary object across the network using sockets in C#.
I'm used to Java and how that works, new to C#. In Java I can create a Socket, create an OutputObjectStream, and just send the object. I don't need to concern myself with serialization.
On the other side, I also have a socket, I create an ObjectInputStream, read the object, and I can then cast the object back to the original type.
Java example:
ObjectInputStream inFromClient = new ObjectInputStream (socket.getInputStream());
Object read = inFromClient.readObject();
if(read instanceof bool) {
// cast read to bool, and call relevant method
} else if(read instanceof UserInfo) {
// cast read to UserInfo...
} else if(read instanceof CarInfo) {
// cast read to CarInfo...
}
But in C# (I'm using JSON), as far as I can tell, I need to first convert my Object to JSON, then to byte[] then send it. On the other side, I convert from byte[] to string, and then to JSON. I use the DataContractJsonSerializer, and it needs to know, which object I expect to get out again. But I don't have that information.
My current solution is to send twice every time. First object sent is a method name (represented as an enum), and the second object sent is the actual object. Based on the first received method name, I know what the second object should be, and can tell this to my JSON serializer wrapper. Something like this:
public static T FromJSON<T>(string json) {
var ms1 = new MemoryStream(Encoding.ASCII.GetBytes(json));
DataContractJsonSerializer dataContractJsonSerializer = new DataContractJsonSerializer(typeof(T));
T sm1 = (T) dataContractJsonSerializer.ReadObject(ms1);
return sm1;
I could probably optimize a little bit, and create a wrapper class, e.g. SocketMessage, which will hold the enum method name, and an argument of type string to hold the JSON string. But is that really the way to do it?
Is there no "easy" solution like in Java?
It doesn't necessarily need to be Sockets, but that's what I'm familiar with. I just need a computer running the server, and a computer next to it running a client, so something other than Sockets might work. They'll be on the same network, so no fancy webstuff, I think. I need an open two-way connection.
Upvotes: 1
Views: 960
Reputation: 4177
There is a couple of things you can do to make this a little easier:
DataContractSerializer
. Plus, you can:TypeNameHandling.Object
for example. (You should not use that to communicate outside your network, for security reasons)Putting it together:
// 'client' side
using (var socket = new Socket(SocketType.Stream, ProtocolType.IPv6))
using (var networkStream = new NetworkStream(socket))
using (var writer = new StreamWriter(networkStream))
using (var jsonWriter = new JsonTextWriter(writer))
{
socket.Connect("localhost", 8888);
var user = new UserInfo { Name = "Jesse de Wit" }; // That's me
var settings = new JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.Objects
};
var serializer = JsonSerializer.Create(settings);
serializer.Serialize(jsonWriter, user);
}
// 'server' side
using (var socket = new Socket(SocketType.Stream, ProtocolType.IPv6))
using (var networkStream = new NetworkStream(socket))
using (var reader = new StreamReader(networkStream))
using (var jsonReader = new JsonTextReader(reader))
{
socket.Accept();
var settings = new JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.Objects
};
var serializer = JsonSerializer.Create(settings);
// Note that obj will be a JObject if no type information is included.
object obj = serializer.Deserialize(jsonReader);
if (obj is UserInfo user)
{
// Jesse de Wit
Console.WriteLine(user.Name);
}
}
Upvotes: 2
Reputation: 33242
Providing that in c# you can even use dynamic
as a result of a JSon Parse, by using newtonsoft library, so serializing the string as is could be an option,and in the other side you can probably understand what type is by looking at key properties on the object.
Upvotes: 0