
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.119.192.176] |
![]() |
|
Сообщ.
#1
,
|
|
|
Добрый день.
Пишу клиент-серверное приложение обмена сообщениями с использованием асинхронных сокетов. Приведу вкратце код программ Код сервера: ![]() ![]() 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; } } Код клиента: ![]() ![]() 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); } } ... } } Проблема в том, что при непрерывной передаче сообщений от сервера (пинг, список клиентов и т.д.) часть сообщений "съедается". Полагаю, что связано это с тем, что в момент когда пришло сообщение, еще не был установлен колбэк.. Как устранить такие потери? |