NetworkStream.Read не работает при первом вызове - PullRequest
1 голос
/ 30 декабря 2010

У меня есть простая программа чата tcp / ip с сервером и клиентом. В первый раз, когда я отправляю пакет, он передается клиенту, но во время NetworkStream.Read останавливает выполнение и не выдает исключение. Следующий отправленный мной пакет отлично читается и обрабатывается. Еще одна странная вещь, которую я заметил, заключается в том, что MyNetworkStream.DataAvailable всегда ложно, даже если я получаю информацию с сервера, поэтому мне нужно поставить символ отладки и пропустить его. Я хотел бы опубликовать весь свой код, но это долго, поэтому я буду публиковать там, где я читаю и пишу в сетевой поток.

 public void Listen(int byteLength)
        {
            var buffer = new byte[byteLength];
            MySocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(Read), buffer);
        }

        private  void Read(IAsyncResult ar)
        {
            while (MySocket.Connected)
            {
            MyNetworkStream = new NetworkStream(MySocket);
            var buffer = new byte[((byte[])ar.AsyncState).Length];
            if (!MyNetworkStream.DataAvailable)
                throw new Exception("Data not available");
                MyNetworkStream.Read(buffer, 0, buffer.Length); <------Here it stops execution without throwing an exception
                string content = Encoding.ASCII.GetString(buffer);
                if(OnRead == null)
                    continue;
                var e = new CommandEventArgs( null, content);
                Control target = null;
                if (OnRead.Target is Control)
                    target = (Control)OnRead.Target;
                if (target != null && target.InvokeRequired)
                    target.Invoke(OnRead, this, e);
                else
                    OnRead(this,e);

            }
        }


        public void Write(string message)
        {
            try
            { 
                var buffer = Encoding.ASCII.GetBytes(message);
                MySocket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, null, null);
                if (OnWrite != null)
                {
                    var target = (Control)OnWrite.Target;
                    if (target != null && target.InvokeRequired)
                    {
                        target.Invoke(OnWrite, this, new EventArgs());
                    }
                    else
                    {
                        OnWrite(this, new EventArgs());
                    }
                }
            }
            catch
            {

            }
        }

Ответы [ 3 ]

2 голосов
/ 30 декабря 2010

BeginReceive асинхронно ожидает сообщения и заполняет ваш буфер.Затем вы начинаете синхронное чтение из сокета, перезаписывая первое сообщение в процессе.

Вы должны вызвать EndReceive, который возвращает количество прочитанных байтов, затем обработать ваш буфер перед попыткой прочитать больше байтов.*

1 голос
/ 30 декабря 2010

Я не уверен, имеет ли это прямое отношение к проблеме, но вы неправильно используете метод Read.Вы читаете данные в буфер, но игнорируете, сколько фактически было прочитано данных, предполагая, что вызов Read всегда возвращает столько данных, сколько вы запрашиваете, поэтому вы декодируете весь буфер, хотя он может быть не полностью заполнен.

Получите возвращаемое значение вызова Read, чтобы вы знали, какая часть буфера фактически заполнена данными:

int len = MyNetworkStream.Read(buffer, 0, buffer.Length);
string content = Encoding.ASCII.GetString(buffer, 0, len);
0 голосов
/ 30 декабря 2010

Вам необходимо реализовать EndRecieve, чтобы получить полные данные из потока.Извлеките следующий пример из MSDN:

public static void Read_Callback(IAsyncResult ar){
    StateObject so = (StateObject) ar.AsyncState;
    Socket s = so.workSocket;

int read = s.EndReceive(ar);

if (read > 0) {
        so.sb.Append(Encoding.ASCII.GetString(so.buffer, 0, read));
        s.BeginReceive(so.buffer, 0, StateObject.BUFFER_SIZE, 0, 
                                 new AsyncCallback(Async_Send_Receive.Read_Callback), so);
}
else{
     if (so.sb.Length > 1) {
          //All of the data has been read, so displays it to the console
          string strContent;
          strContent = so.sb.ToString();
          Console.WriteLine(String.Format("Read {0} byte from socket" + 
                           "data = {1} ", strContent.Length, strContent));
     }
     s.Close();
}
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...