NetworkComms网络通信框架序言

Networkcomms网络通信框架来自于英国,支持以xamarin.ios的方式开发苹果应用程序

其开源版本2.3.1中带有一个示例程序,实现聊天功能,只要输入对方手机的IP和端口就能够显示聊天,可以作为学习networkcomms框架的入门程序

using System;
using System.Collections.Generic;
using System.Linq;

using MonoTouch.Foundation;
using MonoTouch.UIKit;
using NetworkCommsDotNet;

namespace ExamplesChat.iOS
{
    // The UIApplicationDelegate for the application. This class is responsible for launching the
    // User Interface of the application, as well as listening (and optionally responding) to
    // application events from iOS.
    [Register("AppDelegate")]
    public partial class AppDelegate : UIApplicationDelegate
    {
        // class-level declarations
        public override UIWindow Window
        {
            get;
            set;
        }

        /// <summary>
        /// If the application is minimised we need to correctly shutdown NetworkComms.Net
        /// </summary>
        /// <param name="application"></param>
        public override void DidEnterBackground(UIApplication application)
        {
            NetworkComms.Shutdown();
        }
    }
}

AppDelegate.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using NetworkCommsDotNet;
using DPSBase;

namespace ExamplesChat.iOS
{
    /// <summary>
    /// In an attempt to keep things as clear as possible all shared implementation across chat examples
    /// has been provided in this base class.
    /// </summary>
    public abstract class ChatAppBase
    {
        #region Private Fields
        /// <summary>
        /// A boolean used to track the very first initialisation
        /// </summary>
        protected bool FirstInitialisation { get; set; }

        /// <summary>
        /// Dictionary to keep track of which peer messages have already been written to the chat window
        /// </summary>
        protected Dictionary<ShortGuid, ChatMessage> lastPeerMessageDict = new Dictionary<ShortGuid, ChatMessage>();

        /// <summary>
        /// The maximum number of times a chat message will be relayed
        /// </summary>
        ;

        /// <summary>
        /// A local counter used to track the number of messages sent from
        /// this instance.
        /// </summary>
        ;

        /// <summary>
        /// An optional encryption key to use should one be required.
        /// This can be changed freely but must obviously be the same
        /// for both sender and reciever.
        /// </summary>
        string _encryptionKey = "ljlhjf8uyfln23490jf;m21-=scm20--iflmk;";
        #endregion

        #region Public Fields
        /// <summary>
        /// The type of connection currently used to send and recieve messages. Default is TCP.
        /// </summary>
        public ConnectionType ConnectionType { get; set; }

        /// <summary>
        /// The IP address of the server
        /// </summary>
        public string ServerIPAddress { get; set; }

        /// <summary>
        /// The port of the server
        /// </summary>
        public int ServerPort { get; set; }

        /// <summary>
        /// The local name used when sending messages
        /// </summary>
        public string LocalName { get; set; }

        /// <summary>
        /// A boolean used to track if the local device is acting as a server
        /// </summary>
        public bool LocalServerEnabled { get; set; }

        /// <summary>
        /// A boolean used to track if encryption is currently being used
        /// </summary>
        public bool EncryptionEnabled { get; set; }
        #endregion

        /// <summary>
        /// Constructor for ChatAppBase
        /// </summary>
        public ChatAppBase(string name, ConnectionType connectionType)
        {
            LocalName = name;
            ConnectionType = connectionType;

            //Initialise the default values
            ServerIPAddress = "";
            ServerPort = ;
            LocalServerEnabled = false;
            EncryptionEnabled = false;
            FirstInitialisation = true;
        }

        #region NetworkComms.Net Methods
        /// <summary>
        /// Updates the configuration of this instance depending on set fields
        /// </summary>
        public void RefreshNetworkCommsConfiguration()
        {
            #region First Initialisation
            //On first initilisation we need to configure NetworkComms.Net to handle our incoming packet types
            //We only need to add the packet handlers once. If we call NetworkComms.Shutdown() at some future point these are not removed.
            if (FirstInitialisation)
            {
                FirstInitialisation = false;

                //Configure NetworkComms.Net to handle any incoming packet of type 'ChatMessage'
                //e.g. If we recieve a packet of type 'ChatMessage' execute the method 'HandleIncomingChatMessage'
                NetworkComms.AppendGlobalIncomingPacketHandler<ChatMessage>("ChatMessage", HandleIncomingChatMessage);

                //Configure NetworkComms.Net to perform some action when a connection is closed
                //e.g. When a connection is closed execute the method 'HandleConnectionClosed'
                NetworkComms.AppendGlobalConnectionCloseHandler(HandleConnectionClosed);
            }
            #endregion

            #region Optional Encryption
            //Configure encryption if requested
            if (EncryptionEnabled && !NetworkComms.DefaultSendReceiveOptions.DataProcessors.Contains(DPSBase.DPSManager.GetDataProcessor<DPSBase.RijndaelPSKEncrypter>()))
            {
                //Encryption is currently implemented using a pre-shared key (PSK) system
                //NetworkComms.Net supports multiple data processors which can be used with any level of granularity
                //To enable encryption globally (i.e. for all connections) we first add the encryption password as an option
                DPSBase.RijndaelPSKEncrypter.AddPasswordToOptions(NetworkComms.DefaultSendReceiveOptions.Options, _encryptionKey);
                //Finally we add the RijndaelPSKEncrypter data processor to the sendReceiveOptions
                NetworkComms.DefaultSendReceiveOptions.DataProcessors.Add(DPSBase.DPSManager.GetDataProcessor<DPSBase.RijndaelPSKEncrypter>());
            }
            else if (!EncryptionEnabled && NetworkComms.DefaultSendReceiveOptions.DataProcessors.Contains(DPSBase.DPSManager.GetDataProcessor<DPSBase.RijndaelPSKEncrypter>()))
            {
                //If encryption has been disabled but is currently enabled
                //To disable encryption we just remove the RijndaelPSKEncrypter data processor from the sendReceiveOptions
                NetworkComms.DefaultSendReceiveOptions.DataProcessors.Remove(DPSBase.DPSManager.GetDataProcessor<DPSBase.RijndaelPSKEncrypter>());
            }
            #endregion

            #region Local Server Mode and Connection Type Changes
            if (LocalServerEnabled && ConnectionType == ConnectionType.TCP && !TCPConnection.Listening())
            {
                //If we were previously listening for UDP we first shutdown comms.
                if (UDPConnection.Listening())
                {
                    AppendLineToChatHistory("Connection mode has been changed. Any existing connections will be closed.");
                    NetworkComms.Shutdown();
                }
                else
                {
                    AppendLineToChatHistory("Enabling local server mode. Any existing connections will be closed.");
                    NetworkComms.Shutdown();
                }

                //Start listening for new incoming TCP connections
                //Parameter is true so that we listen on a random port if the default is not available
                TCPConnection.StartListening(true);

                //Write the IP addresses and ports that we are listening on to the chatBox
                AppendLineToChatHistory("Listening for incoming TCP connections on:");
                foreach (var listenEndPoint in TCPConnection.ExistingLocalListenEndPoints())
                    AppendLineToChatHistory(listenEndPoint.Address + ":" + listenEndPoint.Port);

                //Add a blank line after the initialisation output
                AppendLineToChatHistory(System.Environment.NewLine);
            }
            else if (LocalServerEnabled && ConnectionType == ConnectionType.UDP && !UDPConnection.Listening())
            {
                //If we were previously listening for TCP we first shutdown comms.
                if (TCPConnection.Listening())
                {
                    AppendLineToChatHistory("Connection mode has been changed. Any existing connections will be closed.");
                    NetworkComms.Shutdown();
                }
                else
                {
                    AppendLineToChatHistory("Enabling local server mode. Any existing connections will be closed.");
                    NetworkComms.Shutdown();
                }

                //Start listening for new incoming UDP connections
                //Parameter is true so that we listen on a random port if the default is not available
                UDPConnection.StartListening(true);

                //Write the IP addresses and ports that we are listening on to the chatBox
                AppendLineToChatHistory("Listening for incoming UDP connections on:");
                foreach (var listenEndPoint in UDPConnection.ExistingLocalListenEndPoints())
                    AppendLineToChatHistory(listenEndPoint.Address + ":" + listenEndPoint.Port);

                //Add a blank line after the initialisation output
                AppendLineToChatHistory(System.Environment.NewLine);
            }
            else if (!LocalServerEnabled && (TCPConnection.Listening() || UDPConnection.Listening()))
            {
                //If the local server mode has been disabled but we are still listening we need to stop accepting incoming connections
                NetworkComms.Shutdown();
                AppendLineToChatHistory("Local server mode disabled. Any existing connections will be closed.");
                AppendLineToChatHistory(System.Environment.NewLine);
            }
            else if (!LocalServerEnabled &&
                ((ConnectionType == ConnectionType.UDP && NetworkComms.GetExistingConnection(ConnectionType.TCP).Count > ) ||
                (ConnectionType == ConnectionType.TCP && NetworkComms.GetExistingConnection(ConnectionType.UDP).Count > )))
            {
                //If we are not running a local server but have changed the connection type after creating connections we need to close
                //existing connections.
                NetworkComms.Shutdown();
                AppendLineToChatHistory("Connection mode has been changed. Existing connections will be closed.");
                AppendLineToChatHistory(System.Environment.NewLine);
            }
            #endregion
        }

        /// <summary>
        /// Performs whatever functions we might so desire when we recieve an incoming ChatMessage
        /// </summary>
        /// <param name="header">The PacketHeader corresponding with the recieved object</param>
        /// <param name="connection">The Connection from which this object was recieved</param>
        /// <param name="incomingMessage">The incoming ChatMessage we are after</param>
        protected virtual void HandleIncomingChatMessage(PacketHeader header, Connection connection, ChatMessage incomingMessage)
        {
            //We only want to write a message once to the chat window
            //Because we support relaying and may recieve the same message twice from multiple sources
            //we use our history and message indexes to ensure we have a new message
            //We perform this action within a lock as HandleIncomingChatMessage could be called in parallel
            lock (lastPeerMessageDict)
            {
                if (lastPeerMessageDict.ContainsKey(incomingMessage.SourceIdentifier))
                {
                    if (lastPeerMessageDict[incomingMessage.SourceIdentifier].MessageIndex < incomingMessage.MessageIndex)
                    {
                        //If this message index is greater than the last seen from this source we can safely
                        //write the message to the ChatBox
                        AppendLineToChatHistory(incomingMessage.SourceName + " - " + incomingMessage.Message);

                        //We now replace the last recieved message with the current one
                        lastPeerMessageDict[incomingMessage.SourceIdentifier] = incomingMessage;
                    }
                }
                else
                {
                    //If we have never had a message from this source before then it has to be new
                    //by defintion
                    lastPeerMessageDict.Add(incomingMessage.SourceIdentifier, incomingMessage);
                    AppendLineToChatHistory(incomingMessage.SourceName + " - " + incomingMessage.Message);
                }
            }

            //This last section of the method is the relay feature
            //We start by checking to see if this message has already been relayed the maximum number of times
            if (incomingMessage.RelayCount < relayMaximum)
            {
                //If we are going to relay this message we need an array of
                //all known connections, excluding the current one
                var allRelayConnections = (from current in NetworkComms.GetExistingConnection() where current != connection select current).ToArray();

                //We increment the relay count before we send
                incomingMessage.IncrementRelayCount();

                //We now send the message to every other connection
                foreach (var relayConnection in allRelayConnections)
                {
                    //We ensure we perform the send within a try catch
                    //To ensure a single failed send will not prevent the
                    //relay to all working connections.
                    try { relayConnection.SendObject("ChatMessage", incomingMessage); }
                    catch (CommsException) { /* Catch the comms exception, ignore and continue */ }
                }
            }
        }

        /// <summary>
        /// Performs whatever functions we might so desire when an existing connection is closed.
        /// </summary>
        /// <param name="connection">The closed connection</param>
        private void HandleConnectionClosed(Connection connection)
        {
            //We are going to write a message to the chat history when a connection disconnects
            //We perform the following within a lock incase mutliple connections disconnect simultaneously
            lock (lastPeerMessageDict)
            {
                //Get the remoteIdentifier from the closed connection
                //This a unique GUID which can be used to identify peers
                ShortGuid remoteIdentifier = connection.ConnectionInfo.NetworkIdentifier;

                //If at any point we recieved a message with a matching identifier we can
                //include the peer name in the disconnection message.
                if (lastPeerMessageDict.ContainsKey(remoteIdentifier))
                    AppendLineToChatHistory("Connection with '" + lastPeerMessageDict[remoteIdentifier].SourceName + "' has been closed.");
                else
                    AppendLineToChatHistory("Connection with '" + connection.ToString() + "' has been closed.");

                //Last thing is to remove this peer from our message history
                lastPeerMessageDict.Remove(connection.ConnectionInfo.NetworkIdentifier);
            }
        }

        /// <summary>
        /// Send a message.
        /// </summary>
        public void SendMessage(string stringToSend)
        {
            //If we have tried to send a zero length string we just return
            if (stringToSend.Trim() == "") return;

            //We may or may not have entered some server connection information
            ConnectionInfo serverConnectionInfo = null;
            if (ServerIPAddress != "")
            {
                try { serverConnectionInfo = new ConnectionInfo(ServerIPAddress, ServerPort); }
                catch (Exception)
                {
                    ShowMessage("Failed to parse the server IP and port. Please ensure it is correct and try again");
                    return;
                }
            }

            //We wrap everything we want to send in the ChatMessage class we created
            ChatMessage chatMessage = new ChatMessage(NetworkComms.NetworkIdentifier, LocalName, stringToSend, messageSendIndex++);

            //We add our own message to the message history incase it gets relayed back to us
            lock (lastPeerMessageDict) lastPeerMessageDict[NetworkComms.NetworkIdentifier] = chatMessage;

            //We write our own message to the chatBox
            AppendLineToChatHistory(chatMessage.SourceName + " - " + chatMessage.Message);

            //Clear the input box text
            ClearInputLine();

            //If we provided server information we send to the server first
            if (serverConnectionInfo != null)
            {
                //We perform the send within a try catch to ensure the application continues to run if there is a problem.
                try
                {
                    if (ConnectionType == ConnectionType.TCP)
                        TCPConnection.GetConnection(serverConnectionInfo).SendObject("ChatMessage", chatMessage);
                    else if (ConnectionType == ConnectionType.UDP)
                        UDPConnection.GetConnection(serverConnectionInfo, UDPOptions.None).SendObject("ChatMessage", chatMessage);
                    else
                        throw new Exception("An invalid connectionType is set.");
                }
                catch (CommsException) { AppendLineToChatHistory("Error: A communication error occured while trying to send message to " + serverConnectionInfo + ". Please check settings and try again."); }
                catch (Exception) { AppendLineToChatHistory("Error: A general error occured while trying to send message to " + serverConnectionInfo + ". Please check settings and try again."); }
            }

            //If we have any other connections we now send the message to those as well
            //This ensures that if we are the server everyone who is connected to us gets our message
            //We want a list of all established connections not including the server if set
            List<ConnectionInfo> otherConnectionInfos;
            if (serverConnectionInfo != null)
                otherConnectionInfos = (from current in NetworkComms.AllConnectionInfo() where current.RemoteEndPoint != serverConnectionInfo.RemoteEndPoint select current).ToList();
            else
                otherConnectionInfos = NetworkComms.AllConnectionInfo();

            foreach (ConnectionInfo info in otherConnectionInfos)
            {
                //We perform the send within a try catch to ensure the application continues to run if there is a problem.
                try
                {
                    if (ConnectionType == ConnectionType.TCP)
                        TCPConnection.GetConnection(info).SendObject("ChatMessage", chatMessage);
                    else if (ConnectionType == ConnectionType.UDP)
                        UDPConnection.GetConnection(info, UDPOptions.None).SendObject("ChatMessage", chatMessage);
                    else
                        throw new Exception("An invalid connectionType is set.");
                }
                catch (CommsException) { AppendLineToChatHistory("Error: A communication error occured while trying to send message to " + info + ". Please check settings and try again."); }
                catch (Exception) { AppendLineToChatHistory("Error: A general error occured while trying to send message to " + info + ". Please check settings and try again."); }
            }

            return;
        }
        #endregion

        #region GUI Interface Methods
        /// <summary>
        /// Outputs the usage instructions to the chat window
        /// </summary>
        public void PrintUsageInstructions()
        {
            AppendLineToChatHistory("");
            AppendLineToChatHistory("Chat usage instructions:");
            AppendLineToChatHistory("");
            AppendLineToChatHistory("Step 1. Open atleast two chat applications. You can choose from Android, Windows Phone, iOS or native Windows versions.");
            AppendLineToChatHistory("Step 2. Enable local server mode in a single application, see settings.");
            AppendLineToChatHistory("Step 3. Provide remote server IP and port information in settings on remaining application.");
            AppendLineToChatHistory("Step 4. Start chatting.");
            AppendLineToChatHistory("");
            AppendLineToChatHistory("Note: Connections are established on the first message send.");
            AppendLineToChatHistory("");
        }

        /// <summary>
        /// Append the provided message to the chat history text box.
        /// </summary>
        /// <param name="message">Message to be appended</param>
        public abstract void AppendLineToChatHistory(string message);

        /// <summary>
        /// Clears the chat history
        /// </summary>
        public abstract void ClearChatHistory();

        /// <summary>
        /// Clears the input text box
        /// </summary>
        public abstract void ClearInputLine();

        /// <summary>
        /// Show a message box as an alternative to writing to the chat history
        /// </summary>
        /// <param name="message">Message to be output</param>
        public abstract void ShowMessage(string message);
        #endregion
    }
}

ChatAppBase

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using NetworkCommsDotNet;

namespace ExamplesChat.iOS
{
    /// <summary>
    /// All NetworkComms.Net implementation can be found here and in ChatAppBase
    /// </summary>
    public class ChatAppiOS : ChatAppBase
    {
        #region Public Fields
        /// <summary>
        /// Size of the chat history view when the keyboard is hidden
        /// </summary>
        , , , );

        /// <summary>
        /// Reference to the chatHistory text view.
        /// </summary>
        public UITextView ChatHistoryBox { get; private set; }

        /// <summary>
        /// Reference to the message box.
        /// </summary>
        public UITextField MessageBox { get; private set; }
        #endregion

        /// <summary>
        /// Constructor for the iOS chat app.
        /// </summary>
        public ChatAppiOS(UITextView chatHistoryBox, UITextField messageBox)
            : base("iPhone", ConnectionType.TCP)
        {
            ChatHistoryBox = chatHistoryBox;
            MessageBox = messageBox;
        }

        #region GUI Interface Overrides
        public override void AppendLineToChatHistory(string message)
        {
            ChatHistoryBox.InvokeOnMainThread(new NSAction(() =>
            {
                ChatHistoryBox.Text += message + Environment.NewLine;
                PointF bottomOffset = , ChatHistoryBox.ContentSize.Height - ChatHistoryBox.Bounds.Size.Height);
                ChatHistoryBox.SetContentOffset(bottomOffset, true);
            }));
        }

        public override void ClearChatHistory()
        {
            ChatHistoryBox.InvokeOnMainThread(new NSAction(() =>
            {
                ChatHistoryBox.Text = "";
                PointF bottomOffset = , ChatHistoryBox.ContentSize.Height - ChatHistoryBox.Bounds.Size.Height);
                ChatHistoryBox.SetContentOffset(bottomOffset, true);
            }));
        }

        public override void ClearInputLine()
        {
            MessageBox.InvokeOnMainThread(new NSAction(() =>
            {
                MessageBox.Text = "";
            }));
        }

        public override void ShowMessage(string message)
        {
            throw new NotImplementedException();
        }
        #endregion
    }
}

ChatAppiOS

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

//We need to add the following two namespaces to this class
using NetworkCommsDotNet;
using ProtoBuf;

namespace ExamplesChat.iOS
{
    /// <summary>
    /// A wrapper class for the messages that we intend to send and recieve.
    /// The [ProtoContract] attribute informs NetworkCommsDotNet that we intend to
    /// serialise (turn into bytes) this object. At the base level the
    /// serialisation is performed by protobuf.net.
    /// </summary>
    [ProtoContract]
    public class ChatMessage
    {
        /// <summary>
        /// The source identifier of this ChatMessage.
        /// We use this variable as the constructor for the ShortGuid.
        /// The [ProtoMember(1)] attribute informs the serialiser that when
        /// an object of type ChatMessage is serialised we want to include this variable
        /// </summary>
        [ProtoMember()]
        string _sourceIdentifier;

        /// <summary>
        /// The source identifier is accessible as a ShortGuid
        /// </summary>
        public ShortGuid SourceIdentifier { get { return new ShortGuid(_sourceIdentifier); } }

        /// <summary>
        /// The name of the source of this ChatMessage.
        /// We use shorthand declaration, get and set.
        /// The [ProtoMember(2)] attribute informs the serialiser that when
        /// an object of type ChatMessage is serialised we want to include this variable
        /// </summary>
        [ProtoMember()]
        public string SourceName { get; private set; }

        /// <summary>
        /// The actual message.
        /// </summary>
        [ProtoMember()]
        public string Message { get; private set; }

        /// <summary>
        /// The index of this message. Every message sent by a particular source
        /// has an incrementing index.
        /// </summary>
        [ProtoMember()]
        public long MessageIndex { get; private set; }

        /// <summary>
        /// The number of times this message has been relayed.
        /// </summary>
        [ProtoMember()]
        public int RelayCount { get; private set; }

        /// <summary>
        /// We must include a public parameterless constructor to be used by the deserialisation step.
        /// </summary>
        public ChatMessage() { }

        /// <summary>
        /// Create a new ChatMessage
        /// </summary>
        /// <param name="sourceIdentifier">The source identifier</param>
        /// <param name="sourceName">The source name</param>
        /// <param name="message">The message to be sent</param>
        /// <param name="messageIndex">The index of this message</param>
        public ChatMessage(ShortGuid sourceIdentifier, string sourceName, string message, long messageIndex)
        {
            this._sourceIdentifier = sourceIdentifier;
            this.SourceName = sourceName;
            this.Message = message;
            this.MessageIndex = messageIndex;
            ;
        }

        /// <summary>
        /// Increment the relay count variable
        /// </summary>
        public void IncrementRelayCount()
        {
            RelayCount++;
        }
    }
}

ChatMessage

// This file has been autogenerated from parsing an Objective-C header file added in Xcode.

using System;
using System.Linq;
using System.Net;
using System.Collections.Generic;
using System.Drawing;
using System.IO;

using MonoTouch.Foundation;
using MonoTouch.UIKit;

using NetworkCommsDotNet;
using DPSBase;

namespace ExamplesChat.iOS
{
    public partial class ChatWindow : UIViewController
    {
        public static ChatAppiOS ChatApplication { get; set; }

        public ChatWindow (IntPtr handle) : base (handle)
        {

        }

        /// <summary>
        /// On load initialise the example
        /// </summary>
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();

            //Subscribe to the keyboard events
            NSNotificationCenter.DefaultCenter.AddObserver(UIKeyboard.DidHideNotification, HandleKeyboardDidHide);
            NSNotificationCenter.DefaultCenter.AddObserver(UIKeyboard.DidShowNotification, HandleKeyboardDidShow);

            //Remove the keyboard if the screen is tapped
            var tap = new UITapGestureRecognizer();
            tap.AddTarget(() =>
            {
                this.View.EndEditing(true);
            });
            this.View.AddGestureRecognizer(tap);

            //Create the chat application instance
            ChatApplication = new ChatAppiOS(ChatHistory, MessageBox);

            //Uncomment this line to enable logging
            //EnableLogging();

            //Print out the application usage instructions
            ChatApplication.PrintUsageInstructions();

            //Initialise comms to add the neccessary packet handlers
            ChatApplication.RefreshNetworkCommsConfiguration();
        }

        /// <summary>
        /// Enable logging, usefull for debugging applications.
        /// </summary>
        private void EnableLogging()
        {
            //We will create the log file in the local documents directory
            string logFileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "NetworkCommsLog.txt");
            ChatApplication.AppendLineToChatHistory("Logging enabled to " + logFileName);

            NetworkComms.EnableLogging(logFileName);
        }

        #region Event Handlers
        /// <summary>
        /// Sends the message when send button is clicked
        /// </summary>
        /// <param name="sender"></param>
        partial void SendButtonClick(NSObject sender)
        {
            ChatApplication.SendMessage(MessageBox.Text);
        }

        /// <summary>
        /// Resize the view to take into account the keyboard position
        /// </summary>
        /// <param name="notification"></param>
        void HandleKeyboardDidShow(NSNotification notification)
        {
            ChatApplication.ClearInputLine();

            NSObject value = notification.UserInfo[UIKeyboard.FrameEndUserInfoKey];
            RectangleF keyboardFrame = ((NSValue)value).RectangleFValue;

            ChatView.Frame = new System.Drawing.RectangleF(ChatView.Frame.X, ChatView.Frame.Y, ChatView.Frame.Width, ChatView.Frame.Height - keyboardFrame.Height);
            PointF bottomOffset = , ChatHistory.ContentSize.Height - ChatHistory.Bounds.Size.Height);
            ChatHistory.SetContentOffset(bottomOffset, true);
        }

        /// <summary>
        /// Resize the view once the keyboard has been minimised
        /// </summary>
        /// <param name="notification"></param>
        private void HandleKeyboardDidHide(NSNotification notification)
        {
            //Set back to original size
            ChatView.Frame = ChatApplication.OriginalViewSize;
        }
        #endregion
    }
}

ChatWindow

using System;
using System.Collections.Generic;
using System.Linq;

using MonoTouch.Foundation;
using MonoTouch.UIKit;

namespace ExamplesChat.iOS
{
    public class Application
    {
        // This is the main entry point of the application.
        static void Main(string[] args)
        {
            // if you want to use a different Application Delegate class from "AppDelegate"
            // you can specify it here.
            UIApplication.Main(args, null, "AppDelegate");
        }
    }
}

Application

// This file has been autogenerated from parsing an Objective-C header file added in Xcode.

using System;

using MonoTouch.Foundation;
using MonoTouch.UIKit;

using NetworkCommsDotNet;

namespace ExamplesChat.iOS
{
    public partial class Settings : UIViewController
    {
        public Settings (IntPtr handle) : base (handle)
        {
        }

        /// <summary>
        /// On load set the config as per the chat application
        /// </summary>
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();

            //Remove the keyboard on a tap gesture
            var tap = new UITapGestureRecognizer();
            tap.AddTarget(() =>
            {
                this.View.EndEditing(true);
            });
            this.View.AddGestureRecognizer(tap);

            //Get a reference to the chat application
            ChatAppiOS chatApplication = ChatWindow.ChatApplication;

            //Update the settings based on previous values
            LocalServerEnabled.SetState(chatApplication.LocalServerEnabled, false);
            MasterIP.Text = chatApplication.ServerIPAddress;
            MasterPort.Text = chatApplication.ServerPort.ToString();
            LocalName.Text = chatApplication.LocalName;
            EncryptionEnabled.SetState(chatApplication.EncryptionEnabled, false);

            //Set the correct segment on the connection mode toggle
            ConnectionMode.SelectedSegment = (chatApplication.ConnectionType == ConnectionType.TCP ?  : );
        }

        /// <summary>
        /// Update the settings when the user goes back to the main interface
        /// </summary>
        /// <returns></returns>
        public override bool ResignFirstResponder()
        {
            //Get a reference to the chat application
            ChatAppiOS chatApplication = ChatWindow.ChatApplication;

            //Parse settings and store back in chat application
            chatApplication.ServerIPAddress = MasterIP.Text.Trim();

            ;
            int.TryParse(MasterPort.Text, out port);
            chatApplication.ServerPort = port;

            chatApplication.LocalName = LocalName.Text.Trim();
            chatApplication.EncryptionEnabled = EncryptionEnabled.On;
            chatApplication.LocalServerEnabled = LocalServerEnabled.On;

            )
                chatApplication.ConnectionType = ConnectionType.TCP;
            else
                chatApplication.ConnectionType = ConnectionType.UDP;

            //Refresh the NetworkComms.Net configuration once any changes have been made
            chatApplication.RefreshNetworkCommsConfiguration();

            return base.ResignFirstResponder();
        }
    }
}

Settings

工程文件下载地址   networkcomm2.3.1开源通信框架下载网页

www.networkcomms.cn

用c#开发苹果应用程序 xamarin.ios方式的更多相关文章

  1. 【转】如何开发苹果iOS操作平台下的应用程序?

    原文网址:http://zhidao.baidu.com/link?url=vxRWjCchSstFmVKvxEqLqfqomu2h5kF-NLAIVEehQgN_FnYtEi4f5yPMS6ywbU ...

  2. Xamarin iOS开发实战第1章使用C#编写第一个iOS应用程序

    Xamarin iOS开发实战第1章使用C#编写第一个iOS应用程序 C#原本是用来编写Windows以及Windows Phone的应用程序.自从Xamarin问世后.C#的作用就发生了非常大的变化 ...

  3. 【Xamarin挖墙脚系列:Xamarin.IOS的程序的结构】

    原文:[Xamarin挖墙脚系列:Xamarin.IOS的程序的结构] 开始熟悉Xamarin在开发IOS的结构!!!!!!! 先看官方 这个是以一个单页面的程序进行讲述的. 1 程序引用的程序集,核 ...

  4. Xamarin.iOS开发初体验

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKwAAAA+CAIAAAA5/WfHAAAJrklEQVR4nO2c/VdTRxrH+wfdU84pW0

  5. Xamarin iOS编写第一个应用程序创建工程

    Xamarin iOS编写第一个应用程序创建工程 在Xcode以及Xamarin安装好后,就可以在Xamarin Studio中编写程序了.本节将主要讲解在Xamarin Studio中如何进行工程的 ...

  6. iOS Simulator功能介绍关于Xamarin IOS开发

    iOS Simulator功能介绍关于Xamarin IOS开发 iOS Simulator功能介绍 在图1.38所示的运行效果中,所见到的类似于手机的模型就是iOS Simulator.在没有iPh ...

  7. Xamarin iOS开发中的编辑、连接、运行

    Xamarin iOS开发中的编辑.连接.运行 创建好工程后,就可以单击Xamarin Studio上方的运行按钮,如图1.37所示,对HelloWorld项目进行编辑.连接以及运行了.运行效果如图1 ...

  8. Visual Studio跨平台开发实战(2) - Xamarin.iOS基本控制项介绍

    原文 Visual Studio跨平台开发实战(2) - Xamarin.iOS基本控制项介绍 前言 在上一篇文章中, 我们介绍了Xamarin 以及简单的HelloWorld范例, 这次我们针对iO ...

  9. 使用Xamarin开发手机聊天程序 -- 基础篇(大量图文讲解 step by step,附源码下载)

    如果是.NET开发人员,想学习手机应用开发(Android和iOS),Xamarin 无疑是最好的选择,编写一次,即可发布到Android和iOS平台,真是利器中的利器啊!而且,Xamarin已经被微 ...

随机推荐

  1. 《FLASH CC 2015 CANVAS 中文教程》——1、导出canvas动画,文件结构浅析

    注::如果你对 FLASH 这个软件操作不够熟悉,建议你可以先看看FLASH动画之类的书. :FLASH CC 在文中直接简称为CC. :以下所以文章中所说的快捷键 如果你按了不起作用,请检查是否有其 ...

  2. c 函数调用产生的汇编指令和数据在内存情况(2)

    c 函数调用产生的汇编指令和数据在内存情况(1) 一直对函数调用的具体汇编指令和各种变量在内存的具体分配,一知半解.各种资料都很详细,但是不实践,不亲自查看下内存总不能笃定.那就自己做下. 两个目的: ...

  3. ubuntu_杂

    1. 虚拟机安装的 ubuntu 12.04,在关闭了 一段时间不操作就屏保 和 锁屏 之后, 在一段时间之后 虚拟机的屏幕还是变黑了,貌似是 os将 显示器关闭了. 这个相关的设置是在哪里? 相关设 ...

  4. JSP连接数据库的两种方式:Jdbc-Odbc桥和Jdbc直连(转)

    学JSP的同学都要知道怎么连数据库,网上的示例各有各的做法,弄得都不知道用谁的好.其实方法千变万化,本质上就两种:Jdbc-Odbc桥和Jdbc直连. 下面先以MySQL为例说说这两种方式各是怎么连的 ...

  5. 统一事件源epoll代码示例

    可以将信号注册进pipe管道的写端,通过对读端的监听,来实现统一事件源. #include <sys/types.h> #include <sys/socket.h> #inc ...

  6. iOS开发之.pch文件初识

    pch全称是“precompiled header”,即预编译头文件,自Xcode6诞生之日起,便在Supporting Files文件下消失多年.说起苹果对pch的爱恨情仇,其分析pch的作用便不言 ...

  7. double 逆序

    请设计一个函数,不许用到字符串函数,用数学运算,将double类型数据转换,例如123.456转换成654.321 int _tmain(int argc, _TCHAR* argv[]) { con ...

  8. java按值传递相关理解

    Java没有引用传递只有按值传递,没有引用传递只有按值传递,值传递. 1. public class Test {     public static void main(String[] args ...

  9. 20160808_Linux服务

    1. http://bbs.csdn.net/topics/370100269 2. http://blog.csdn.net/csfreebird/article/details/8239933 h ...

  10. python操作mongodb之五大量写操作

    import pymongo #库名 db = pymongo.MongoClient('192.168.30.252',27017).bulk_example #test集合插入 db.test.i ...