private void AcceptClient(IAsyncResult ar) { TcpClient newClient; try { // a new connection has been accepted newClient = _listener.EndAcceptTcpClient(ar); Debug.WriteLine("Listener established TCP connection with " + ((IPEndPoint)newClient.Client.RemoteEndPoint).Address.ToString()); } catch (ObjectDisposedException) { // occurs if we close the TCP listener while waiting for data return; } catch (IOException ex) { Debug.WriteLine("Caught [" + ex.GetType().ToString() + "]\n\n" + ex.StackTrace); return; } catch (SocketException ex) { Debug.WriteLine("Caught [" + ex.GetType().ToString() + "]\n\n" + ex.StackTrace); return; } // keep listening for more connections _listenerAsyncResult = _listener.BeginAcceptTcpClient(AcceptClient, new object()); NetworkStream ns = newClient.GetStream(); IPAddress addr = ((IPEndPoint)newClient.Client.RemoteEndPoint).Address; TcpPeerConnection conn = new TcpPeerConnection(newClient, ns, addr); // add connection to the peer list if (_peerConns.ContainsKey(addr)) { try { _peerConns[addr].stream.Close(); _peerConns[addr].client.Close(); } catch (Exception e) { // eat exception - exceptions likely when closing a dead connection that's been reopened Debug.WriteLine("Exception while closing connection assumed to be dead"); Debug.WriteLine(e); } _peerConns[addr] = conn; } else { _peerConns.Add(addr, conn); } // asynchronously read data from the connection. When data arrives, ReceiveData() will be called // todo this can throw an exception ns.BeginRead(conn.buffer, 0, conn.buffer.Length, ReceiveData, conn); }
private void ConnectedToPeer(IAsyncResult ar) { TcpPeerConnection conn = (TcpPeerConnection)ar.AsyncState; IPAddress addr = conn.remoteAddress; // check if connection was successful if (!conn.client.Connected) { Debug.WriteLine("Failed to connect to " + addr.ToString()); return; } conn.stream = conn.client.GetStream(); // see if we already have a connection to this peer -- if so, close it if (_peerConns.ContainsKey(addr)) { TcpPeerConnection oldConn = _peerConns[addr]; try { oldConn.stream.Close(); oldConn.client.Close(); } catch (Exception ex) { Debug.WriteLine("Caught " + ex.ToString() + " while closing old connection"); } finally { _peerConns.Remove(addr); } } // store the peer in our peers list _peerConns.Add(addr, conn); Debug.WriteLine("Established connection to " + addr.ToString()); // see if the peer has any data to send us conn.stream.BeginRead(conn.buffer, 0, conn.buffer.Length, ReceiveData, conn); // send any queued messages to the peer Queue <Message> q = _sendQueue[addr]; Message sendThis = q.Dequeue(); if (sendThis != null) { SendMessage(sendThis, addr); } }
private void DataSent(IAsyncResult ar) { TcpPeerConnection conn = (TcpPeerConnection)ar.AsyncState; try { conn.stream.EndWrite(ar); } catch (SocketException ex) { Debug.Write("Caught SocketException in DataSent"); Debug.Write(ex); try { conn.stream.Close(); conn.client.Close(); } catch (Exception) { // have to eat it } } catch (IOException ex) { Debug.Write("Caught IOException in DataSent"); Debug.Write(ex); try { conn.stream.Close(); conn.client.Close(); } catch (Exception) { // have to eat it } } catch (ObjectDisposedException ex) { // occurs if we close the TCP connection while trying to send data Debug.Write("Caught ObjectDisposedException in DataSent"); Debug.Write(ex); return; } }
public void SendMessage(Message msg, IPAddress addr) { // see if we have an existing connection to this peer TcpPeerConnection conn; if (_peerConns.ContainsKey(addr)) { // convert message to bytes and send it conn = _peerConns[addr]; try { byte[] msgBytes = Encoding.ASCII.GetBytes(msg.Serialize()); conn.stream.BeginWrite(msgBytes, 0, msgBytes.Length, DataSent, conn); return; } catch (SocketException ex) { Debug.Write("Caught SocketException in SendMessage"); Debug.Write(ex); try { conn.stream.Close(); conn.client.Close(); } catch (Exception) { // have to eat it } // fall through queue the message instead } catch (IOException ex) { Debug.Write("Caught IOException in SendMessage"); Debug.Write(ex); try { conn.stream.Close(); conn.client.Close(); } catch (Exception) { // have to eat it } // fall through queue the message instead } catch (ObjectDisposedException ex) { // occurs if we close the TCP connection while trying to send data Debug.Write("Caught ObjectDisposedException in SendMessage"); Debug.Write(ex); return; } } // either we didn't have an active connection, or we tried to send on our active connection and failed, // so add the message to the queue if (!_sendQueue.ContainsKey(addr)) { _sendQueue.Add(addr, new Queue <Message>()); } _sendQueue[addr].Enqueue(msg); // connect to the peer conn = new TcpPeerConnection(null, null, addr); TcpClient client = new TcpClient(); conn.client = client; client.BeginConnect(addr, Port, ConnectedToPeer, conn); // ConnectedToPeer() will send the message once we're connected }