Beispiel #1
0
        /// <summary>
        /// To be used as the callback for accepting a new client that was initiated by StartServer, and
        /// continues an event-loop to accept additional clients.
        ///
        /// Uses EndAcceptSocket to finalize the connection and create a new SocketState. The SocketState's
        /// OnNetworkAction should be set to the delegate that was passed to StartServer.
        /// Then invokes the OnNetworkAction delegate with the new SocketState so the user can take action.
        ///
        /// If anything goes wrong during the connection process (such as the server being stopped externally),
        /// the OnNetworkAction delegate should be invoked with a new SocketState with its ErrorOccured flag set to true
        /// and an appropriate message placed in its ErrorMessage field. The event-loop should not continue if
        /// an error occurs.
        ///
        /// If an error does not occur, after invoking OnNetworkAction with the new SocketState, an event-loop to accept
        /// new clients should be continued by calling BeginAcceptSocket again with this method as the callback.
        /// </summary>
        /// <param name="ar">The object asynchronously passed via BeginAcceptSocket. It must contain a tuple with
        /// 1) a delegate so the user can take action (a SocketState Action), and 2) the TcpListener</param>
        private static void AcceptNewClient(IAsyncResult ar)
        {
            Tuple <Action <SocketState>, TcpListener> temp = (Tuple <Action <SocketState>, TcpListener>)ar.AsyncState;

            try
            {
                SocketState ss = new SocketState(temp.Item1, temp.Item2.EndAcceptSocket(ar));
                ss.OnNetworkAction(ss);
                temp.Item2.BeginAcceptSocket(AcceptNewClient, temp);
            }

            catch
            {
                SocketState ss = new SocketState(temp.Item1, null);
                ss.ErrorOccured = true;
                ss.ErrorMessage = "Connection Failed";
                ss.OnNetworkAction(ss);
            }
        }
Beispiel #2
0
        /// <summary>
        /// To be used as the callback for accepting a new client that was initiated by StartServer, and
        /// continues an event-loop to accept additional clients.
        ///
        /// Uses EndAcceptSocket to finalize the connection and create a new SocketState. The SocketState's
        /// OnNetworkAction should be set to the delegate that was passed to StartServer.
        /// Then invokes the OnNetworkAction delegate with the new SocketState so the user can take action.
        ///
        /// If anything goes wrong during the connection process (such as the server being stopped externally),
        /// the OnNetworkAction delegate should be invoked with a new SocketState with its ErrorOccured flag set to true
        /// and an appropriate message placed in its ErrorMessage field. The event-loop should not continue if
        /// an error occurs.
        ///
        /// If an error does not occur, after invoking OnNetworkAction with the new SocketState, an event-loop to accept
        /// new clients should be continued by calling BeginAcceptSocket again with this method as the callback.
        /// </summary>
        /// <param name="ar">The object asynchronously passed via BeginAcceptSocket. It must contain a tuple with
        /// 1) a delegate so the user can take action (a SocketState Action), and 2) the TcpListener</param>
        private static void AcceptNewClient(IAsyncResult ar)
        {
            Console.WriteLine("contact from client");

            // Grabbing Tuple that has the Action<SocketState> and TCPListener from StartServer method.
            Tuple <Action <SocketState>, TcpListener> tuple = (Tuple <Action <SocketState>, TcpListener>)ar.AsyncState;


            // Grabbing the new client to be added
            try
            {
                Socket      newClient = listener.EndAcceptSocket(ar);
                SocketState state     = new SocketState(tuple.Item1, newClient);

                state.OnNetworkAction(state);

                // Keep track of the client so we can broadcast to all of them
                lock (clients)
                {
                    clients.Add(newClient);
                }
            }

            // Error Finalizing connection / Calling OnNetworkAction
            catch
            {
                SocketState ssError = new SocketState(tuple.Item1, null);
                ssError.ErrorOccured = true;
                ssError.ErrorMessage = "Error while trying to connect.";
                ssError.OnNetworkAction(ssError);
            }

            try
            {
                // resumes an accept loop
                listener.BeginAcceptSocket(AcceptNewClient, tuple);
            }

            catch
            {
                // Do nothing
            }
        }
Beispiel #3
0
 /// <summary>
 /// To be used as the callback for accepting a new client that was initiated by StartServer, and
 /// continues an event-loop to accept additional clients.
 ///
 /// Uses EndAcceptSocket to finalize the connection and create a new SocketState. The SocketState's
 /// OnNetworkAction should be set to the delegate that was passed to StartServer.
 /// Then invokes the OnNetworkAction delegate with the new SocketState so the user can take action.
 ///
 /// If anything goes wrong during the connection process (such as the server being stopped externally),
 /// the OnNetworkAction delegate should be invoked with a new SocketState with its ErrorOccured flag set to true
 /// and an appropriate message placed in its ErrorMessage field. The event-loop should not continue if
 /// an error occurs.
 ///
 /// If an error does not occur, after invoking OnNetworkAction with the new SocketState, an event-loop to accept
 /// new clients should be continued by calling BeginAcceptSocket again with this method as the callback.
 /// </summary>
 /// <param name="ar">The object asynchronously passed via BeginAcceptSocket. It must contain a tuple with
 /// 1) a delegate so the user can take action (a SocketState Action), and 2) the TcpListener</param>
 private static void AcceptNewClient(IAsyncResult ar)
 {
     try
     {
         Tuple <Action <SocketState>, TcpListener> args = (Tuple <Action <SocketState>, TcpListener>)ar.AsyncState;
         Action <SocketState> toCall   = args.Item1;                   //get toCall delegate
         TcpListener          listener = args.Item2;                   //get TcpListener we have initialized in StartServer
         Socket      client            = listener.EndAcceptSocket(ar); // finalize connection
         SocketState soc_state         = new SocketState(toCall, client);
         soc_state.OnNetworkAction(soc_state);
         // if nothing goes wrong, then starting accepting socket again
         listener.BeginAcceptSocket(AcceptNewClient, args);
     }
     catch (Exception e)
     {
         SocketState soc_state = new SocketState(s => { }, null); // should be fine passed null
         soc_state.OnNetworkAction(soc_state);
         soc_state.ErrorOccured = true;
         soc_state.ErrorMessage = e.Message;
     }
 }
Beispiel #4
0
        /////////////////////////////////////////////////////////////////////////////////////////
        // Server-Side Code
        /////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Starts a TcpListener on the specified port and starts an event-loop to accept new clients.
        /// The event-loop is started with BeginAcceptSocket and uses AcceptNewClient as the callback.
        /// AcceptNewClient will continue the event-loop.
        /// </summary>
        /// <param name="toCall">The method to call when a new connection is made</param>
        /// <param name="port">The the port to listen on</param>
        public static TcpListener StartServer(Action <SocketState> toCall, int port)
        {
            TcpListener listener = new TcpListener(IPAddress.Any, port);
            Tuple <Action <SocketState>, TcpListener> temp = new Tuple <Action <SocketState>, TcpListener>(toCall, listener);

            try
            {
                listener.Start();
                listener.BeginAcceptSocket(AcceptNewClient, temp);
            }

            catch
            {
                SocketState ss = new SocketState(toCall, null);
                ss.ErrorOccured = true;
                ss.ErrorMessage = "Connection Failed";
                ss.OnNetworkAction(ss);
            }

            return(listener);
        }
        /// <summary>
        /// To be used as the callback for finalizing a receive operation that was initiated by GetData.
        ///
        /// Uses EndReceive to finalize the receive.
        ///
        /// As stated in the GetData documentation, if an error occurs during the receive process,
        /// either this method or GetData (not both) should indicate the error appropriately.
        ///
        /// If data is successfully received:
        ///  (1) Read the characters as UTF8 and put them in the SocketState's unprocessed data buffer (its string builder).
        ///      This must be done in a thread-safe manner with respect to the SocketState methods that access or modify its
        ///      string builder.
        ///  (2) Call the saved delegate (OnNetworkAction) allowing the user to deal with this data.
        /// </summary>
        /// <param name="ar">
        /// This contains the SocketState that is stored with the callback when the initial BeginReceive is called.
        /// </param>
        private static void ReceiveCallback(IAsyncResult ar)
        {
            SocketState state = (SocketState)ar.AsyncState;

            try {
                int numBytes = state.TheSocket.EndReceive(ar);  //finalizes recieve process

                if (numBytes == 0)
                {
                    throw new Exception("Socket closed during data transfer");
                }

                lock (state.data) {
                    state.data.Append(Encoding.UTF8.GetString(state.buffer, 0, numBytes)); //appends data from buffer that is converted from bytes to UTF8 text
                }
                state.OnNetworkAction(state);
            }
            catch (Exception e) {
                HandleError(state.OnNetworkAction, e.Message);
            }
        }
Beispiel #6
0
        /// <summary>
        /// To be used as the callback for accepting a new client that was initiated by StartServer, and
        /// continues an event-loop to accept additional clients.
        ///
        /// Uses EndAcceptSocket to finalize the connection and create a new SocketState. The SocketState's
        /// OnNetworkAction should be set to the delegate that was passed to StartServer.
        /// Then invokes the OnNetworkAction delegate with the new SocketState so the user can take action.
        ///
        /// If anything goes wrong during the connection process (such as the server being stopped externally),
        /// the OnNetworkAction delegate should be invoked with a new SocketState with its ErrorOccured flag set to true
        /// and an appropriate message placed in its ErrorMessage field. The event-loop should not continue if
        /// an error occurs.
        ///
        /// If an error does not occur, after invoking OnNetworkAction with the new SocketState, an event-loop to accept
        /// new clients should be continued by calling BeginAcceptSocket again with this method as the callback.
        /// </summary>
        /// <param name="ar">The object asynchronously passed via BeginAcceptSocket. It must contain a tuple with
        /// 1) a delegate so the user can take action (a SocketState Action), and 2) the TcpListener</param>
        private static void AcceptNewClient(IAsyncResult ar)
        {
            //initializes the variables used in this method
            SocketState          socketState = null;
            Action <SocketState> action      = null;
            TcpListener          listener    = null;
            Socket socket = null;

            try
            {
                //Creates a tuple from the given parameter and sets the listener and action to the given items
                Tuple <Action <SocketState>, TcpListener> tuplePassed = (Tuple <Action <SocketState>, TcpListener>)ar.AsyncState;
                action   = tuplePassed.Item1;
                listener = tuplePassed.Item2;

                socket = listener.EndAcceptSocket(ar);
                //creates a new socketstate with the socketstate and the socket from the tuple
                socketState = new SocketState(action, socket);
            }
            //Catches any Exception Thrown and creates a new scoket state to nofify the user
            catch (Exception e)
            {
                socketState = new SocketState(action, socket);
                socketState.ErrorOccured = true;
                socketState.ErrorMessage = e.Message;
                action(socketState);
                return;
            }

            socketState.OnNetworkAction(socketState);
            try
            {
                //starts accepting new clients from the listener inside of the tuple
                Tuple <Action <SocketState>, TcpListener> tuple = new Tuple <Action <SocketState>, TcpListener>(action, listener);
                listener.BeginAcceptSocket(AcceptNewClient, tuple);
            }
            catch (Exception e)
            {
            }
        }
Beispiel #7
0
        /// <summary>
        /// To be used as the callback for finalizing a receive operation that was initiated by GetData.
        ///
        /// Uses EndReceive to finalize the receive.
        ///
        /// As stated in the GetData documentation, if an error occurs during the receive process,
        /// either this method or GetData (not both) should indicate the error appropriately.
        ///
        /// If data is successfully received:
        ///  (1) Read the characters as UTF8 and put them in the SocketState's unprocessed data buffer (its string builder).
        ///      This must be done in a thread-safe manner with respect to the SocketState methods that access or modify its
        ///      string builder.
        ///  (2) Call the saved delegate (OnNetworkAction) allowing the user to deal with this data.
        /// </summary>
        /// <param name="ar">
        /// This contains the SocketState that is stored with the callback when the initial BeginReceive is called.
        /// </param>
        private static void ReceiveCallback(IAsyncResult ar)
        {
            SocketState socketState = (SocketState)ar.AsyncState;

            try {
                int numBytesReceived = socketState.TheSocket.EndReceive(ar);
                if (numBytesReceived > 0)
                {
                    lock (socketState.data) {
                        socketState.data.Append(Encoding.UTF8.GetString(socketState.buffer, 0, numBytesReceived));
                    }
                    socketState.OnNetworkAction(socketState);
                }
                else
                {
                    // if we receive 0 bytes, that's an error.
                    throw new NetworkingException("received 0 bytes");
                }
            } catch (Exception e) {
                HandleError(socketState, e);
            }
        }
Beispiel #8
0
        /// <summary>
        /// To be used as the callback for accepting a new client that was initiated by StartServer, and
        /// continues an event-loop to accept additional clients.
        ///
        /// Uses EndAcceptSocket to finalize the connection and create a new SocketState. The SocketState's
        /// OnNetworkAction should be set to the delegate that was passed to StartServer.
        /// Then invokes the OnNetworkAction delegate with the new SocketState so the user can take action.
        ///
        /// If anything goes wrong during the connection process (such as the server being stopped externally),
        /// the OnNetworkAction delegate should be invoked with a new SocketState with its ErrorOccured flag set to true
        /// and an appropriate message placed in its ErrorMessage field. The event-loop should not continue if
        /// an error occurs.
        ///
        /// If an error does not occur, after invoking OnNetworkAction with the new SocketState, an event-loop to accept
        /// new clients should be continued by calling BeginAcceptSocket again with this method as the callback.
        /// </summary>
        /// <param name="ar">The object asynchronously passed via BeginAcceptSocket. It must contain a tuple with
        /// 1) a delegate so the user can take action (a SocketState Action), and 2) the TcpListener</param>
        private static void AcceptNewClient(IAsyncResult ar)
        {
            Tuple <Action <SocketState>, TcpListener> tuple = (Tuple <Action <SocketState>, TcpListener>)ar.AsyncState;

            TcpListener          listener = tuple.Item2;
            Action <SocketState> toCall   = tuple.Item1;

            try
            {
                SocketState socketState = new SocketState(toCall, listener.EndAcceptSocket(ar));
                socketState.OnNetworkAction(socketState);

                Tuple <Action <SocketState>, TcpListener> tcpInfo = new Tuple <Action <SocketState>, TcpListener>(toCall, listener);
                listener.BeginAcceptSocket(AcceptNewClient, tcpInfo);
            }
            catch
            {
                SocketState errorSocketState = new SocketState(toCall, null);
                errorSocketState.ErrorOccured = true;
                errorSocketState.ErrorMessage = "Error occurred while accepting a new client";

                errorSocketState.OnNetworkAction(errorSocketState);
            }
        }
        /// <summary>
        /// To be used as the callback for finalizing a connection process that was initiated by ConnectToServer.
        ///
        /// Uses EndConnect to finalize the connection.
        ///
        /// As stated in the ConnectToServer documentation, if an error occurs during the connection process,
        /// either this method or ConnectToServer (not both) should indicate the error appropriately.
        ///
        /// If a connection is successfully established, invokes the toCall Action that was provided to ConnectToServer (above)
        /// with a new SocketState representing the new connection.
        ///
        /// </summary>
        /// <param name="ar">The object asynchronously passed via BeginConnect</param>
        private static void ConnectedCallback(IAsyncResult ar)
        {
            SocketState state = (SocketState)ar.AsyncState;

            //Check if state is connected.
            if (!state.TheSocket.Connected)
            {
                //No Need to do anything else in this method.
                return;
            }

            try
            {
                state.TheSocket.EndConnect(ar);
            }
            catch (Exception e)
            {
                SendErrorMessage(new SocketState(state.OnNetworkAction, new Socket(IPAddress.None.AddressFamily, SocketType.Stream, ProtocolType.Tcp)),
                                 e.Message + "\nError Caught in ConnectedCallback.");
                return;
            }

            state.OnNetworkAction(state);
        }
Beispiel #10
0
        /////////////////////////////////////////////////////////////////////////////////////////
        // Client-Side Code
        /////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Begins the asynchronous process of connecting to a server via BeginConnect,
        /// and using ConnectedCallback as the method to finalize the connection once it's made.
        ///
        /// If anything goes wrong during the connection process, toCall should be invoked
        /// with a new SocketState with its ErrorOccured flag set to true and an appropriate message
        /// placed in its ErrorMessage field. Between this method and ConnectedCallback, toCall should
        /// only be invoked once on error.
        ///
        /// This connection process should timeout and produce an error (as discussed above)
        /// if a connection can't be established within 3 seconds of starting BeginConnect.
        ///
        /// </summary>
        /// <param name="toCall">The action to take once the connection is open or an error occurs</param>
        /// <param name="hostName">The server to connect to</param>
        /// <param name="port">The port on which the server is listening</param>
        public static void ConnectToServer(Action <SocketState> toCall, string hostName, int port)
        {
            // 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)
                {
                    SocketState errorSocketState = new SocketState(toCall, null);
                    errorSocketState.ErrorOccured = true;
                    errorSocketState.ErrorMessage = "Couldn't find any IPV4 addresses";

                    errorSocketState.OnNetworkAction(errorSocketState);
                    return;
                }
            }
            catch (Exception)
            {
                // See if host name is a valid ipaddress
                try
                {
                    ipAddress = IPAddress.Parse(hostName);
                }
                catch (Exception)
                {
                    SocketState errorSocketState = new SocketState(toCall, null);
                    errorSocketState.ErrorOccured = true;
                    errorSocketState.ErrorMessage = "Host name isn't a valid ipaddress";

                    errorSocketState.OnNetworkAction(errorSocketState);
                }
            }

            // Create a TCP/IP socket.
            Socket socket = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

            // This disables Nagle's algorithm (google if curious!)
            // Nagle's algorithm can cause problems for a latency-sensitive
            // game like ours will be
            socket.NoDelay = true;

            try
            {
                SocketState  TheServer = new SocketState(toCall, socket);
                IAsyncResult result    = TheServer.TheSocket.BeginConnect(ipAddress, port, ConnectedCallback, TheServer);
                bool         success   = result.AsyncWaitHandle.WaitOne(3000, true);

                if (!TheServer.TheSocket.Connected)
                {
                    TheServer.TheSocket.Close();
                }
            }
            catch
            {
                SocketState errorSocketState = new SocketState(toCall, null);
                errorSocketState.ErrorOccured = true;
                errorSocketState.ErrorMessage = "An error occured while connecting to server";

                errorSocketState.OnNetworkAction(errorSocketState);
            }
        }
 /// <summary>
 /// indicate an error to the user by invoking the OnNetworkAction delegate with an error socket state.
 /// </summary>
 public static void HandleError(SocketState socketState, Exception e)
 {
     socketState = SetSocketStateError(socketState, e.Message);
     socketState.OnNetworkAction(socketState);
 }
Beispiel #12
0
        /////////////////////////////////////////////////////////////////////////////////////////
        // Client-Side Code
        /////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Begins the asynchronous process of connecting to a server via BeginConnect,
        /// and using ConnectedCallback as the method to finalize the connection once it's made.
        ///
        /// If anything goes wrong during the connection process, toCall should be invoked
        /// with a new SocketState with its ErrorOccured flag set to true and an appropriate message
        /// placed in its ErrorMessage field. Between this method and ConnectedCallback, toCall should
        /// only be invoked once on error.
        ///
        /// This connection process should timeout and produce an error (as discussed above)
        /// if a connection can't be established within 3 seconds of starting BeginConnect.
        ///
        /// </summary>
        /// <param name="toCall">The action to take once the connection is open or an error occurs</param>
        /// <param name="hostName">The server to connect to</param>
        /// <param name="port">The port on which the server is listening</param>
        public static void ConnectToServer(Action <SocketState> toCall, string hostName, int port)
        {
            // TODO: This method is incomplete, but contains a starting point
            //       for decoding a host address

            // Establish the remote endpoint for the socket.
            IPHostEntry ipHostInfo;
            IPAddress   ipAddress = IPAddress.None;
            SocketState temp      = new SocketState(toCall, null);

            // 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)
                {
                    temp.ErrorOccured = true;
                    temp.ErrorMessage = "Couldn't find IPv4";
                    temp.OnNetworkAction(temp);
                }
            }
            catch (Exception)
            {
                // see if host name is a valid ipaddress
                try
                {
                    ipAddress = IPAddress.Parse(hostName);
                }
                catch (Exception)
                {
                    temp.ErrorOccured = true;
                    temp.ErrorMessage = "Host name not valid";
                    temp.OnNetworkAction(temp);
                }
            }

            // Create a TCP/IP socket.
            Socket socket = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

            // This disables Nagle's algorithm (google if curious!)
            // Nagle's algorithm can cause problems for a latency-sensitive
            // game like ours will be
            socket.NoDelay = true;

            temp = new SocketState(toCall, socket);

            try
            {
                bool success = socket.BeginConnect(ipAddress, port, ConnectedCallback, temp).AsyncWaitHandle.WaitOne(3000, true);
                if (!success)
                {
                    temp.ErrorOccured = true;
                    temp.ErrorMessage = "Connection Timeout Error";
                    temp.OnNetworkAction(temp);
                }
            }

            catch
            {
                temp.ErrorOccured = true;
                temp.ErrorMessage = "Connection Failed";
                temp.OnNetworkAction(temp);
            }
        }
        /////////////////////////////////////////////////////////////////////////////////////////
        // Helper Methods
        /////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Sets the ErrorOccured flag on a given SocketState to true, sets the SocketState's error message,
        /// then, invokes the SocketState's OnNetworkAction.
        /// </summary>
        /// <param name="errorState">The state to send the error on</param>
        /// <param name="message">The error message</param>
        private static void SendErrorMessage(SocketState errorState, string message)
        {
            errorState.ErrorOccured = true;
            errorState.ErrorMessage = message;
            errorState.OnNetworkAction(errorState);
        }
Beispiel #14
0
        /////////////////////////////////////////////////////////////////////////////////////////
        // Client-Side Code
        /////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Begins the asynchronous process of connecting to a server via BeginConnect,
        /// and using ConnectedCallback as the method to finalize the connection once it's made.
        ///
        /// If anything goes wrong during the connection process, toCall should be invoked
        /// with a new SocketState with its ErrorOccured flag set to true and an appropriate message
        /// placed in its ErrorMessage field. Between this method and ConnectedCallback, toCall should
        /// only be invoked once on error.
        ///
        /// This connection process should timeout and produce an error (as discussed above)
        /// if a connection can't be established within 3 seconds of starting BeginConnect.
        ///
        /// /// ADDED: Ref for Connection timeout:
        /// https://stackoverflow.com/questions/17118632/how-to-set-the-timeout-for-a-tcpclient
        ///
        /// </summary>
        /// <param name="toCall">The action to take once the connection is open or an error occurs</param>
        /// <param name="hostName">The server to connect to</param>
        /// <param name="port">The port on which the server is listening</param>
        public static void ConnectToServer(Action <SocketState> toCall, string hostName, int port)
        {
            // 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)
                {
                    SocketState ssError = new SocketState(toCall, new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp));
                    ssError.ErrorOccured = true;
                    ssError.ErrorMessage = "Was unable to identify an IPV4 address.";
                    ssError.OnNetworkAction(ssError);
                }
            }
            catch (Exception)
            {
                // see if host name is a valid ipaddress
                try
                {
                    ipAddress = IPAddress.Parse(hostName);
                }

                catch (Exception)
                {
                    SocketState ssError = new SocketState(toCall, new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp));
                    ssError.ErrorOccured = true;
                    ssError.ErrorMessage = "Invalid IPAddress.";
                    ssError.OnNetworkAction(ssError);
                }
            }

            // Create a TCP/IP socket.
            Socket socket = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

            // This disables Nagle's algorithm (google if curious!)
            // Nagle's algorithm can cause problems for a latency-sensitive
            // game like ours will be
            socket.NoDelay = true;

            // Creates a new Socket for data result
            SocketState state = new SocketState(toCall, socket);

            // Attempting BeginConnect
            try
            {
                IAsyncResult result = state.TheSocket.BeginConnect(ipAddress, port, ConnectedCallback, state);

                // Checking for timeout
                bool success = result.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(3));
                if (!success)
                {
                    // Close the socket and report the error
                    socket.Close();
                    SocketState TimeoutSS = new SocketState(toCall, new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp));
                    TimeoutSS.ErrorOccured = true;
                    TimeoutSS.ErrorMessage = "Connection Timeout after 3 seconds.";
                }
            }

            catch (Exception)
            {
                // Do nothing
            }
        }
Beispiel #15
0
        /////////////////////////////////////////////////////////////////////////////////////////
        // Client-Side Code
        /////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Begins the asynchronous process of connecting to a server via BeginConnect,
        /// and using ConnectedCallback as the method to finalize the connection once it's made.
        ///
        /// If anything goes wrong during the connection process, toCall should be invoked
        /// with a new SocketState with its ErrorOccured flag set to true and an appropriate message
        /// placed in its ErrorMessage field. Between this method and ConnectedCallback, toCall should
        /// only be invoked once on error.
        ///
        /// This connection process should timeout and produce an error (as discussed above)
        /// if a connection can't be established within 3 seconds of starting BeginConnect.
        ///
        /// </summary>
        /// <param name="toCall">The action to take once the connection is open or an error occurs</param>
        /// <param name="hostName">The server to connect to</param>
        /// <param name="port">The port on which the server is listening</param>
        public static void ConnectToServer(Action <SocketState> toCall, string hostName, int port)
        {
            // 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)
                {
                    //Indicate an error to the user, as specified in the documentation
                    SocketState errorState = new SocketState(toCall, new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp));
                    //Set error state and message
                    errorState.ErrorOccured = true;
                    errorState.ErrorMessage = "IPV4 addresses were not found";
                    //Run delegate with error flag
                    errorState.OnNetworkAction(errorState);
                    return;
                }
            }
            catch (Exception)
            {
                // see if host name is a valid ipaddress
                try
                {
                    ipAddress = IPAddress.Parse(hostName);
                }
                catch (Exception)
                {
                    //IP address was not found, so we create a new SocketState and set error flag to true
                    SocketState invalidIpAddress = new SocketState(toCall, new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp));
                    invalidIpAddress.ErrorOccured = true;
                    //Set the message and fire the SocketState delegate
                    invalidIpAddress.ErrorMessage = "The IP address entered is not valid";
                    invalidIpAddress.OnNetworkAction(invalidIpAddress);
                    return;
                }
            }
            try
            {
                // Create a TCP/IP socket.
                Socket socket = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                //Create Tuple to hold information that needs to be passed to the callback
                Tuple <Socket, Action <SocketState> > info = new Tuple <Socket, Action <SocketState> >(socket, toCall);

                // This disables Nagle's algorithm (google if curious!)
                // Nagle's algorithm can cause problems for a latency-sensitive
                // game like ours will be
                socket.NoDelay = true;
                //Try catch for the timeout


                // Connect using a timeout (3 seconds)
                //Saves the result of the begin connect without invoking callback to verify timeout does not happen
                IAsyncResult result = socket.BeginConnect(ipAddress, port, null, info);
                // boolean flag to signal timeout, end connection if is not made after 3 seconds
                bool success = result.AsyncWaitHandle.WaitOne(3000, true);
                // Check if timeout condition has been met
                if (success)
                {
                    //Call ConnectedCallBack with the info that was saved
                    ConnectedCallback(result);
                }
                //Else we timed out and we should throw exception
                else
                {
                    throw new Exception();
                }
            }
            // Connection has timed out and we want to close the socket and produce an error
            catch (Exception)
            {
                Socket socket = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

                //Create new state with error flag set and call delegate
                SocketState timeoutState = new SocketState(toCall, socket);
                timeoutState.ErrorOccured = true;
                timeoutState.ErrorMessage = "Connection timed out";
                timeoutState.OnNetworkAction(timeoutState);
            }
        }
Beispiel #16
0
 /// <summary>
 /// Sets the passed in socket states ErrorOccured flag to true
 /// Sets the socket states error message to message
 /// Updates the users delegate with this state
 /// </summary>
 /// <param name="state"></param>
 private static void SetErrorState(SocketState state, string message)
 {
     state.ErrorOccured = true;
     state.ErrorMessage = message;
     state.OnNetworkAction(state);
 }