Как отправить произвольный объект по сети в C # - PullRequest
1 голос
/ 28 июня 2019

Я пытаюсь отправить произвольный объект по сети, используя сокеты в C #.

Я привык к Java и тому, как это работает, впервые в C #.В Java я могу создать Socket, создать OutputObjectStream и просто отправить объект.Мне не нужно заниматься сериализацией.

С другой стороны, у меня также есть сокет, я создаю ObjectInputStream, читаю объект и затем могу привести объект обратно к исходному типу.

Пример Java:

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...
}

Но в C # (я использую JSON), насколько я могу судить, мне нужно сначала преобразовать мой объект в JSON, а затем в байт [] затем отправьте его.С другой стороны, я преобразую из байта [] в строку, а затем в JSON.Я использую DataContractJsonSerializer, и он должен знать, какой объект я ожидаю получить снова.Но у меня нет этой информации.

Мое текущее решение - отправлять дважды каждый раз.Первый отправленный объект - это имя метода (представленное в виде enum), а второй отправленный объект - это реальный объект.Основываясь на имени первого полученного метода, я знаю, каким должен быть второй объект, и могу сообщить об этом моей оболочке сериализатора JSON.Примерно так:

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;

Вероятно, я мог бы немного оптимизировать и создать класс-оболочку, например, SocketMessage, который будет содержать имя метода enum и аргумент типа string для хранения строки JSON.Но так ли это на самом деле?

Нет ли "простого" решения, как в Java?

Это не обязательно должен быть сокет, но это то, что я знакомс.Мне просто нужен компьютер, на котором запущен сервер, и компьютер рядом с ним, на котором работает клиент, так что может работать что-то кроме Sockets.Они будут в одной сети, так что, я думаю, нет ничего интересного.Мне нужно открытое двустороннее соединение.

Ответы [ 2 ]

2 голосов
/ 28 июня 2019

Есть несколько вещей, которые вы можете сделать, чтобы сделать это немного проще:

  • Оберните сокет в NetworkStream .Это позволяет вам читать / записывать из / в поток и несколько упрощает интерфейс для сериализации.
  • Используйте Newtonsoft.Json для сериализации ваших объектов в json и из него.Я считаю, что намного проще в использовании, чем DataContractSerializer.Кроме того, вы можете:
  • Включить информацию о типе в сериализованные объекты.Когда вы используете Newtonsoft.Json, вам не нужно заранее знать тип при десериализации, если информация о типе включена в сериализацию.Для этого, например, установите TypeNameHandling на TypeNameHandling.Object.(Вы не должны использовать это для связи за пределами вашей сети, из соображений безопасности)

Соединение:

// '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);
    }
}
0 голосов
/ 28 июня 2019

При условии, что в c # вы даже можете использовать dynamic в результате анализа JSon, используя библиотеку newtonsoft, поэтому можно сериализовать строку как есть, а с другой стороны вы, вероятно, сможете понять, какой типглядя на ключевые свойства объекта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...