/// <summary> /// Listen for data, while explicitly defining what callback we should use when data is recieved. /// </summary> /// <param name="ss"></param> /// <param name="dataRecievedCallback"></param> public static void listenForData(SocketState ss, SocketState.EventProcessor dataRecievedCallback) { if (!ss.SafeToSendRequest) { return; } ss.TheCallback = dataRecievedCallback; // Start listening for a message // When a message arrives, handle it on a new thread with ReceiveCallback try { ss.TheSocket.BeginReceive(ss.MessageBuffer, 0, ss.MessageBuffer.Length, SocketFlags.None, Networking.ReceiveCallback, ss); } catch (Exception e) { //If An Error Occurs Notify The Socket Owner ss.ErrorOccured = true; ss.ErrorMesssage = e.Message; ss.TheCallback(ss); return; } }
/// <summary> /// The callback to use when we recieve data on the socket. Parcels the data out of our buffer and into /// the SocketState stringGrowableBuffer. /// </summary> /// <param name="ar"></param> private static void ReceiveCallback(IAsyncResult ar) { SocketState ss = (SocketState)ar.AsyncState; int bytesRead; try { bytesRead = ss.TheSocket.EndReceive(ar); } catch (Exception e) { //If An Error Occurs Notify The Socket Owner ss.ErrorOccured = true; ss.ErrorMesssage = e.Message; ss.TheCallback(ss); return; } // socket wants to be closed if (bytesRead == 0) { Disconnect(ss, false); return; } // If the socket is still open if (bytesRead > 0) { lock (ss.StringGrowableBuffer) { string theMessage = Encoding.UTF8.GetString(ss.MessageBuffer, 0, bytesRead); // Append the received data to the growable buffer. // It may be an incomplete message, so we need to start building it up piece by piece ss.StringGrowableBuffer.Append(theMessage); } ss.TheCallback(ss); } }
/// <summary> /// The callback to use when we're finalizing the initial network connect. /// </summary> /// <param name="ar"></param> private static void ConnectedToNetworkNode(IAsyncResult ar) { SocketState ss = (SocketState)ar.AsyncState; try { // Complete the connection. ss.TheSocket.EndConnect(ar); } catch (Exception e) { ss.ErrorOccured = true; ss.ErrorMesssage = e.Message; ss.TheCallback(ss); return; } ss.SafeToSendRequest = true; // Call The Callback To Signal The Connection Is Complete ss.TheCallback(ss); }
/// <summary> /// The AsyncCallback that we use when disconnecting. /// </summary> /// <param name="ar"></param> private static void DisconnectedCallback(IAsyncResult ar) { SocketState ss = (SocketState)ar.AsyncState; try { ss.TheSocket.EndDisconnect(ar); } catch (Exception e) { ss.ErrorOccured = true; ss.ErrorMesssage = e.Message; } ss.TheCallback(ss); }
/// <summary> /// Start attempting to connect to the server /// </summary> /// <param name="host_name"> server to connect to </param> /// <returns></returns> public static Socket ConnectToNetworkNode(string hostName, SocketState.EventProcessor nodeConnectedCallback, int port = DEFAULT_PORT, int timeoutMs = -1) { System.Diagnostics.Debug.WriteLine("connecting to " + hostName); // Connect to a remote device. try { // Establish the remote endpoint for the socket. IPHostEntry ipHostInfo; IPAddress ipAddress = IPAddress.None; // Determine if the server address is a URL or an IP try { ipHostInfo = Dns.GetHostEntry(hostName); bool foundIPV4 = false; foreach (IPAddress addr in ipHostInfo.AddressList) { if (addr.AddressFamily != AddressFamily.InterNetworkV6) { foundIPV4 = true; ipAddress = addr; break; } } // Didn't find any IPV4 addresses if (!foundIPV4) { System.Diagnostics.Debug.WriteLine("Invalid addres: " + hostName); return(null); } } catch (Exception) { // see if host name is actually an ipaddress, i.e., 155.99.123.456 System.Diagnostics.Debug.WriteLine("using IP"); ipAddress = IPAddress.Parse(hostName); } // Create a TCP/IP socket. Socket socket = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp); socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, false); SocketState newSocketState = new SocketState(socket, nodeConnectedCallback); IAsyncResult result = socket.BeginConnect(ipAddress, port, Networking.ConnectedToNetworkNode, newSocketState); bool timedOut = !result.AsyncWaitHandle.WaitOne(timeoutMs, true); if (timedOut) { newSocketState.ErrorOccured = true; newSocketState.ErrorMesssage = "Timeout: Couldn't Connect With The Server"; newSocketState.TheCallback(newSocketState); socket.Close(); } return(socket); } catch (Exception e) { SocketState errorSocketState = new SocketState(null, nodeConnectedCallback); errorSocketState.ErrorOccured = true; errorSocketState.ErrorMesssage = e.Message; errorSocketState.TheCallback(errorSocketState); return(null); } }