2016-09-07 18 views
2

Идея этого небольшого проекта заключается в разработке приложения чата с той разницей, что я хочу отправлять объекты вместо простых строк. Пока это то, что у меня есть.Исключение из памяти с BeginRead

Если я десериализую конструктор, он отлично работает (на данный момент у пользователя есть только 2 строковых поля), однако я планирую, что у вас будет несколько клиентов, отправляющих данные на сервер в любое время. Мне сложно понять, как это работает и как исправить ошибку (например, это дает «Исключение типа« Исключение System.OutOfMemoryException »было выбрано.» В строке Deseralize) даже после прочтения документации MS, и я бы как некоторые идеи от вас, ребята.

Обратите внимание на то, кто пытается скомпилировать это: Binaryformatter имеет способ сделать это, как и в: Предположим, что UserDTO имеет строку свойств Имя, строка Email Применяя этот класс к клиенту и серверу, его необходимо построить с помощью класса библиотеку и добавить ссылку на это в оба проекта, потому что как-то бинарныйформатор говорит, что даже если вы создаете один и тот же класс в обоих проектах, десериализируя утверждения, он не может отобразить объект. Я оставлю образец клиента, который я использую ниже.

Сервер:

class Program { 
const int serverPort = 60967; 
static List<UserConnection> clientList = new List<UserConnection>(); 
static TcpListener listener; 
static Thread listenerThread; 


static void Main(string[] args) { 
     listenerThread = new Thread(new ThreadStart(DoListen)); 
     listenerThread.Start(); 
     Console.WriteLine("Server Started"); 
     //while (true) { 
      string a = Console.ReadLine() 
     //} 
    } 

static void DoListen() { 
     try { 
      listener = new TcpListener(System.Net.IPAddress.Any, serverPort); 
      listener.Start(); 
      Console.WriteLine("Listening [...]"); 
      do { 
       UserConnection client = new UserConnection(listener.AcceptTcpClient()); 
       //clientList.Add(client); 
       Console.WriteLine("New connection found"); 
      } while (true); 
     } 
     catch (Exception ex) { 
      Console.WriteLine(ex.ToString()); 
     } 
    } 
} 



public class UserConnection { 
private TcpClient clientInfo; 
private byte[] readBuffer = new byte[2000]; 
const int READ_BUFFER_SIZE = 2000; 

public UserConnection(TcpClient client) { 
    clientInfo = client; 
    clientInfo.GetStream().BeginRead(readBuffer, 0, READ_BUFFER_SIZE, new AsyncCallback(StreamReceiver), null); 
} 

private void StreamReceiver(IAsyncResult ar) { 
    try 
    { 
     if (client.GetStream().CanRead) { 
     lock (clientInfo.GetStream()) { 
      var strm = clientInfo.GetStream(); 
      int BytesRead = clientInfo.GetStream().EndRead(ar); 
      BinaryFormatter formatter = new BinaryFormatter(); 
      var mydat = (UserDTO)formatter.Deserialize(strm); 
     } 
     lock (clientInfo.GetStream()) { 
      clientInfo.GetStream().BeginRead(readBuffer, 0, READ_BUFFER_SIZE, new AsyncCallback(StreamReceiver), null); 
     } 
    } 

    catch (Exception e) { 
    Console.WriteLine(ex.ToString()); 
    } 
} 

Клиент:

class Program { 
    static void Main(string[] args) { 
      ConnectResult("localhost", 60967); 
      Console.ReadLine(); 
     } 
    } 

    static string ConnectResult(string ip, int port) { 
     try { 
      TcpClient client = new TcpClient(ip, port); 
      AttemptLogin(client); 
      return "Connection Succeeded"; 
     } 
     catch (Exception ex) { 
      return "Server is not active. Please start server and try again.  " + ex.ToString(); 
     } 
    } 

    static void AttemptLogin(TcpClient client) { 
     UserDTO obj = new UserDTO("email", "username"); 
     IFormatter formatter = new BinaryFormatter(); 
     var stream = client.GetStream(); 
     formatter.Serialize(stream, obj); 
     Console.WriteLine("Sent Object"); 
    } 
} 
+0

Когда выполняется 'while (true);' loop exit? (Ответ: когда у программы заканчивается память, я полагаю) – Quantic

+0

Просто для тестирования он никогда не выйдет, это в основном десериализующая часть, которая мне тяжело (при работе со строкой и потоковедом она работает просто отлично с несколькими клиенты) – abr

+0

@Quantic Я сомневаюсь, что проблема связана с тем, что цикл не увеличивает объем используемой памяти. – EJoshuaS

ответ

1

Вместо того чтобы делать все BeginRead() звонки, попробуйте просто принимать поток и передать его в метод BinaryFormatter.DeSerialize().

public UserConnection(TcpClient client) { 
    clientInfo = client; 
    //clientInfo.GetStream().BeginRead(readBuffer, 0, READ_BUFFER_SIZE, new AsyncCallback(StreamReceiver), null); 
    var strm = clientInfo.GetStream(); 
    BinaryFormatter formatter = new BinaryFormatter(); 
    var mydat = (UserDTO)formatter.Deserialize(strm); 
} 

Я предполагаю, что позиция вашего потока уже перемещена, если не в конце. Когда вы передаете его в Deserialize(), просто нет данных для чтения. Фактически, ваш byte[] readBuffer, вероятно, имеет все необходимые данные, если ваш DTO не может содержать более 2000 байт. Если это так, то вы должны использовать байты в readBuffer вместо десериализации.

+0

Ну, это работает так, как я писал выше, однако вопрос будет следующим: как пользователь может отправлять данные по асинхронному пути, потому что это будет выполняться только один раз – abr

+1

В этом случае вы в конечном итоге используете 'byte []' у тебя есть. Здесь хранятся все ваши данные. Вы не можете использовать 'GetStream()', потому что он уже был прочитан. 'readBuffer' содержит ваши данные, и вам нужно делать проверки, чтобы узнать, действительно ли все данные на самом деле являются' UserDTO', или если у вас есть только некоторые данные. Суть, не использует поток для Deserialize. Используйте байты, которые вы уже создали для создания объекта. Возможно, вам захочется взглянуть на BitConverter или BinaryReader, если ваш объект может содержать более 2000 байт, потому что, если это так, вам нужно знать, когда начинается/заканчивается UserDTO. – TyCobb

+0

спасибо за помощь, я обновил вопрос, потому что это дает мне странную ошибку atm, как вы думаете, что происходит? – abr

 Смежные вопросы

  • Нет связанных вопросов^_^