/// <summary> /// Метод вызываемый при завершении попытки поключения клиента /// </summary> public void ConnectCallback(IAsyncResult ar) { string result = "OK"; try { // Получаем подключенного клиента TcpClientData myTcpClient = (TcpClientData)ar.AsyncState; NetworkStream ns = myTcpClient.tcpClient.GetStream(); myTcpClient.tcpClient.EndConnect(ar); // Запускаем асинхронный метод чтения сетевых данных для подключенного TCP клиента myTcpClient.buffer = new byte[global.LENGTHHEADER]; ns.BeginRead(myTcpClient.buffer, 0, myTcpClient.buffer.Length, new AsyncCallback(ReadCallback), myTcpClient); // Parent.ChangeBackColor(Color.Goldenrod); } catch (Exception e) { //MessageBox.Show(e.Message); // Обработка ошибок подключения DisconnectClient(); result = "ERR"; // SoundError(); } // Активация события успешного или неуспешного подключения к серверу, // здесь серверу можно отослать ознакомительные данные о себе (например, имя клиента) if (Connected != null) { Connected.BeginInvoke(this, result, null, null); } }
/// <summary> /// Завершение работы подключенного клиента /// </summary> private void DeleteClient(TcpClientData mtc) { if (mtc != null && mtc.tcpClient.Connected == true) { mtc.tcpClient.GetStream().Close(); // по настоянию MSDN закрываем поток отдельно у клиента mtc.tcpClient.Close(); // затем закрываем самого клиента } }
/// <summary> /// Попытка асинхронного подключения клиента к серверу /// </summary> /// <param name="ipserver">IP адрес сервера</param> public void ConnectClient(string ipserver, int port) { if (modeNetwork == Mode.indeterminately) { _tcpClient = new TcpClientData(); _tcpClient.tcpClient.BeginConnect(IPAddress.Parse(ipserver), port, new AsyncCallback(ConnectCallback), _tcpClient); modeNetwork = Mode.Client; } else { // SoundError(); } }
/// <summary> /// Обратный метод завершения принятия клиентов /// </summary> public void AcceptCallback(IAsyncResult ar) { if (modeNetwork == Mode.indeterminately) { return; } TcpListener listener = (TcpListener)ar.AsyncState; try { _tcpClient = new TcpClientData(); _tcpClient.tcpClient = listener.EndAcceptTcpClient(ar); // Немедленно запускаем асинхронный метод извлечения сетевых данных // для акцептированного TCP клиента NetworkStream ns = _tcpClient.tcpClient.GetStream(); _tcpClient.buffer = new byte[global.LENGTHHEADER]; ns.BeginRead(_tcpClient.buffer, 0, _tcpClient.buffer.Length, new AsyncCallback(ReadCallback), _tcpClient); // Продолжаем ждать запросы на подключение listener.BeginAcceptTcpClient(AcceptCallback, listener); // Активация события успешного подключения клиента if (Accept != null) { Accept.BeginInvoke(this, null, null); } } catch (Exception e) { // Обработка исключительных ошибок возникших при акцептирования клиента. SoundError(e.Message); } }
/// <summary> /// Метод асинхронно вызываемый при наличие данных в буферах приема. /// </summary> public void ReadCallback(IAsyncResult ar) { if (modeNetwork == Mode.indeterminately) { return; } TcpClientData myTcpClient = (TcpClientData)ar.AsyncState; try { NetworkStream ns = myTcpClient.tcpClient.GetStream(); int r = ns.EndRead(ar); if (r > 0) { // Из главного заголовка получим размер массива байтов информационного объекта string header = Encoding.Default.GetString(myTcpClient.buffer); int leninfo = int.Parse(header); // Получим и десериализуем объект с подробной информацией о содержании получаемого сетевого пакета MemoryStream ms = new MemoryStream(leninfo); byte[] temp = new byte[leninfo]; r = ns.Read(temp, 0, temp.Length); ms.Write(temp, 0, r); BinaryFormatter bf = new BinaryFormatter(); ms.Position = 0; SendInfo sc = (SendInfo)bf.Deserialize(ms); ms.Close(); object obj = null; if (sc.datasize > 0) { // Создадим файл на основе полученной информации и массива байтов следующих за объектом информации // FileStream fs = new FileStream(sc.filename, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite, sc.filesize); BinaryFormatter _bf = new BinaryFormatter(); MemoryStream _ms = new MemoryStream(); do { temp = new byte[global.MAXBUFFER]; r = ns.Read(temp, 0, temp.Length); // Записываем строго столько байтов сколько прочтено методом Read() _ms.Write(temp, 0, r); // Как только получены все байты файла, останавливаем цикл, // иначе он заблокируется в ожидании новых сетевых данных if (_ms.Length == sc.datasize) { _ms.Position = 0; obj = _bf.Deserialize(_ms); _ms.Close(); break; } }while (r > 0); temp = null; GC.Collect(); GC.WaitForPendingFinalizers(); } if (Receive != null) { Receive(this, new ReceiveEventArgs(sc, (NetworkTransferObjects)obj)); } myTcpClient.buffer = new byte[global.LENGTHHEADER]; ns.BeginRead(myTcpClient.buffer, 0, myTcpClient.buffer.Length, new AsyncCallback(ReadCallback), myTcpClient); } else { DeleteClient(myTcpClient); // Событие клиент отключился if (Disconnected != null) { Disconnected.BeginInvoke(this, "Клиент отключился!", null, null); } } } catch (Exception e) { DeleteClient(myTcpClient); // Событие клиент отключился if (Disconnected != null) { Disconnected.BeginInvoke(this, "Клиент отключился аварийно!", null, null); } SoundError(e.Message); } }