На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
  
> Асинхронные сокеты: пропускаются данные
    Добрый день.
    Пишу клиент-серверное приложение обмена сообщениями с использованием асинхронных сокетов.
    Приведу вкратце код программ
    Код сервера:
    ExpandedWrap disabled
              private void runToolStripMenuItem_Click(object sender, EventArgs e)
              {
                  IPAddress[] aryLocalAddr = null;
                  strHostName = "";
       
                  strHostName = Dns.GetHostName();
                  IPHostEntry ipEntry = Dns.GetHostEntry(strHostName);
                  aryLocalAddr = ipEntry.AddressList;
       
                  int nPortListen = Convert.ToInt32(FormEchoServer.Properties.Settings.Default.ServerPort);
       
                  listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                  listener.Bind(new IPEndPoint(IPAddress.Parse(FormEchoServer.Properties.Settings.Default.ServerAdress), nPortListen));
                  listener.Listen(500);
       
                  listener.BeginAccept(OnConnectRequest, listener);
              }
       
              public void OnConnectRequest(IAsyncResult ar)
              {
                  Socket listener = (Socket)ar.AsyncState;
                      NewConnection(listener.EndAccept(ar));
                      listener.BeginAccept(OnConnectRequest, listener);
              }
       
              public void NewConnection(Socket sockClient)
              {
                  SocketChatClient client = new SocketChatClient(sockClient);
                  client.SetupRecieveCallback(this);
              }
       
             public void OnRecievedData(IAsyncResult ar)
             {
                  SocketChatClient client = (SocketChatClient)ar.AsyncState;
                  byte[] aryRet = client.GetRecievedData(ar);
       
                      // If no data was recieved then the connection is probably dead
                      if (aryRet.Length < 1)
                      {
                          byte[] byteUserDisconnected = Encoding.UTF8.GetBytes("");
                          foreach (ChatClient clientDisconnect in usrList)
                          {
                              if ((clientDisconnect.SocketChatClient == client) && (clientDisconnect.Status != "offline"))
                              {
                                  AddNode2TV(stv_ClientList, clientDisconnect.Login, "offline");
                                  AddText(tb_Log, String.Format("[{0}] Клиент {1} отсоединился\r\n\r\n", DateTime.Now, clientDisconnect.Login));
                                  string userDisconnected = String.Format("[BEGIN]Сервер|?|?|{0} отсоединился|?|?|Client[END]", clientDisconnect.Login);
                                  byteUserDisconnected = Encoding.UTF8.GetBytes(userDisconnected);
                                  clientDisconnect.Offline();
                              }
                          }
       
                          foreach (ChatClient chatclient in usrList)
                          {
                              if ((chatclient.Status == "online") || (chatclient.Status == "away"))
                              {
                                  chatclient.SocketChatClient.Sock.Send(byteUserDisconnected);
                              }
                          }
       
                          client.Sock.Close();
                          return;
                      }
       
                      string strRawMsg = Encoding.UTF8.GetString(aryRet);
                      if (strRawMsg.Contains("[BEGIN]") && strRawMsg.Contains("[END]"))
                      {
                          strRawMsg = strRawMsg.Substring(7);
                          strRawMsg = strRawMsg.Remove(strRawMsg.IndexOf("[END]"));
                      }
                      string[] delimeter = { "|?|?|" };
                      string[] strRawMsgArr = strRawMsg.Split(delimeter, System.StringSplitOptions.RemoveEmptyEntries);
       
                      string msgSender = strRawMsgArr[0];
                      string msg = @strRawMsgArr[1];
                      string msgReciever = strRawMsgArr[2];
       
                      //Здесь в зависимости от полученного сообщения от клиента выполняются разные действия
       
                      // Отправляем сообщение
                      if (msgReciever != "Сервер")
                      {
                          foreach (ChatClient chatclient in usrList)
                          {
                              if ((chatclient.Login == msgReciever) && ((chatclient.Status == "online") || (chatclient.Status == "away")))
                              {
                                  flag = true;
       
                                  try
                                  {
                                      chatclient.SocketChatClient.Sock.Send(aryRet);
                                      // Пишем в базу
                                      ...
                                  }
                              }
                          }
       
                          // Если клиент не в сети
                          if (!flag)
                          {
                              // Пишем в базу                        
                          }
                      }
                      client.SetupRecieveCallback(this);
                  }
              }
       
          // Класс SocketChatClient
          public class SocketChatClient
          {
              private Socket m_sock;                      // Connection to the client
              private byte[] m_byBuff = new byte[12000];      // Receive data buffer
       
              public SocketChatClient(Socket sock)
              {
                  m_sock = sock;
              }
       
              public Socket Sock
              {
                  get { return m_sock; }
              }
       
              public void SetupRecieveCallback(AppMain app)
              {
                  try
                  {
                      AsyncCallback recieveData = app.OnRecievedData;
                      m_sock.BeginReceive(m_byBuff, 0, m_byBuff.Length, SocketFlags.None, recieveData, this);
                  }
                  catch (Exception ex)
                  {
                      string s = ex.Message;
                      //MessageBox.Show(ex.Message.ToString(), "Вызов приема не удался (обратный)");
                  }
              }
       
              public byte[] GetRecievedData(IAsyncResult ar)
              {
                  int nBytesRec = 0;
                  try
                  {
                      nBytesRec = m_sock.EndReceive(ar);
                  }
                  catch { }
                  byte[] byReturn = new byte[nBytesRec];
                  Array.Copy(m_byBuff, byReturn, nBytesRec);
       
                  return byReturn;
              }
          }


    Код клиента:
    ExpandedWrap disabled
      private void Online()
              {            
                      try
                      {
                          if (m_sock != null && m_sock.Connected)
                          {
                              m_sock.Shutdown(SocketShutdown.Both);
                              m_sock.Disconnect(false);
                          }
       
       
                          m_sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
       
                          string ServerAddress = sChatClient.Properties.Settings.Default.IP;
                          int port = Convert.ToInt32(sChatClient.Properties.Settings.Default.Port);
       
                          IPEndPoint epServer = new IPEndPoint(IPAddress.Parse(ServerAddress), port);
       
                          m_sock.Blocking = false;
       
                          AsyncCallback onconnect = OnConnect;
                          m_sock.BeginConnect(epServer, onconnect, m_sock);
       
                          t_Ping = new System.Threading.Timer(t_Ping_Tick, null, 0,89000);
                      }                
              }
       
      public void OnConnect(IAsyncResult ar)
              {
                  try
                  {
                      Socket sock = (Socket)ar.AsyncState;
                      sock.EndConnect(ar);
                      if (sock.Connected)
                      {
                          SetupRecieveCallback(sock);
                          Byte[] byteDateLine = Encoding.UTF8.GetBytes(String.Format("[BEGIN]{0}|?|?|Connected|?|?|{1}[END]", m_userName, "Сервер"));
                          sock.Send(byteDateLine, byteDateLine.Length, 0);
                      }
                      else
                      {
                          TNShow(taskbarNotifierErr, "Сервер", "Соединение не установлено!");
                      }
                  }
                  catch (Exception ex)
                  {
                      TNShow(taskbarNotifierErr, "Сервер", "Ошибка во время соединения!\n" + ex.Message);
                  }
              }
       
      public void SetupRecieveCallback(Socket sock)
              {
                  try
                  {
                      AsyncCallback recieveData = OnRecievedData;
                      sock.BeginReceive(m_byBuff, 0, m_byBuff.Length, SocketFlags.None, recieveData, sock);
                  }
                  ...
              }
       
      public void OnRecievedData(IAsyncResult ar)
              {
                  Socket sock;
                  try
                  {
                      sock = (Socket)ar.AsyncState;
                  }
                  ...
       
                  if ((sock != null) && (sock.Connected))
                  {
                      int nBytesRec = 0;
                      try
                      {
                          nBytesRec = sock.EndReceive(ar);
                      }
                      ...
                      try
                      {
                          if (nBytesRec > 0)
                          {
                              CheckForIllegalCrossThreadCalls = false;
       
                              // Получаем сообщение и разбиваем его
                              string sRecievedRaw = Encoding.UTF8.GetString(m_byBuff, 0, nBytesRec);
       
                              if (sRecievedRaw.Contains("[BEGIN]") && sRecievedRaw.Contains("[END]"))
                              {
                                  sRecievedRaw = sRecievedRaw.Substring(7);
                                  sRecievedRaw = sRecievedRaw.Remove(sRecievedRaw.IndexOf("[END]"));
                              }
                              else
                              {
                                  return;
                              }
       
                              string[] delimeter = { "|?|?|" };
                              string[] strRawMsgArr = sRecievedRaw.Split(delimeter, System.StringSplitOptions.RemoveEmptyEntries);
       
                              string sender = "";
                              string msg = "";
       
                              if (strRawMsgArr.Length >= 2)
                              {
                                  sender = strRawMsgArr[0];
                                  msg = strRawMsgArr[1];
                                  
                              }
       
                              #region Информация от сервера (статусы, контакт листы)
                              ...
                              // Обрабатываем информацию от сервера
                              #endregion
       
                              SetupRecieveCallback(sock);
                          }
                      }
                      ...
                  }
             }


    Проблема в том, что при непрерывной передаче сообщений от сервера (пинг, список клиентов и т.д.) часть сообщений "съедается". Полагаю, что связано это с тем, что в момент когда пришло сообщение, еще не был установлен колбэк.. Как устранить такие потери?
    0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
    0 пользователей:


    Рейтинг@Mail.ru
    [ Script execution time: 0,0241 ]   [ 16 queries used ]   [ Generated: 19.03.24, 06:19 GMT ]