歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

C#的Socket簡單實現消息發送

Socket一般用於網絡之間的通信,在這裡,實現的是服務端與客戶端的簡單消息通信。
首先是客戶端的搭建,一般步驟是先建立Socket綁定本地的IP和端口,並對遠端連接進行連接進行監聽,這裡的監聽一般開啟後台線程進行循環處理;如果遠端有連接到本機的Socket的端口,則獲取一個新的Socket對象並重新添加一個線程用於對遠端地址進行消息通信(消息的收發),這樣,服務端的Socket就簡單實現,下面是winForm的具體實現。

一、先建立Socket的服務類SocketServerManager,用於對Socket各種操作的統一管理:

public class SocketManager
    {
        Socket _socket = null;
        EndPoint _endPoint = null;
        bool _isListening = false;
        int BACKLOG = 10;

        public SocketManager(string ip, int port)
        {
            _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPAddress _ip = IPAddress.Parse(ip);
            _endPoint = new IPEndPoint(_ip, port);
        }

        public void Start()
        {
            _socket.Bind(_endPoint); //綁定端口
            _socket.Listen(BACKLOG); //開啟監聽
            Thread acceptServer = new Thread(AcceptWork); //開啟新線程處理監聽
            acceptServer.IsBackground = true;
            _isListening = true;
            acceptServer.Start();
        }

        public void AcceptWork()
        {
            while (_isListening)
            {
                Socket acceptSocket = _socket.Accept();
                if (acceptSocket != null)
                {
                    Thread socketConnectedThread = new Thread(newSocketReceive);
                    socketConnectedThread.IsBackground = true;
                    socketConnectedThread.Start(acceptSocket);
                }
                Thread.Sleep(200);
            }
        }

        public void newSocketReceive(object obj)
        {
            Socket socket = obj as Socket;
            while (true)
            {
                try
                {
                    if (socket == null) return;
                    //這裡向系統投遞一個接收信息的請求,並為其指定ReceiveCallBack做為回調函數
                    socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, ReceiveCallBack, buffer);
                }
                catch (Exception ex)
                {
                    return;
                }
                Thread.Sleep(100);
            }
        }

        private void ReceiveCallBack(IAsyncResult ar)
        {
        }
    }

public class SockeServertManager

上面是Socket管理類的模型,具體的方法是初始化和開啟監聽,接下來就是在Form的界面調用建立類和Start方法。

客戶端同樣是初始化socket,然後就不是監聽socket,而是調用Connect連接指定的Socket地址,最後是開啟新的線程接收和發送消息。

public class SocketClientManager
    {
        public Socket _socket = null;
        public EndPoint endPoint = null;
        public bool _isConnected = false;

        public SocketClientManager(string ip, int port)
        {
            IPAddress _ip = IPAddress.Parse(ip);
            endPoint = new IPEndPoint(_ip, port);
            _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        }

        public void Start()
        {
            _socket.BeginConnect(endPoint, ConnectedCallback, _socket);
            _isConnected = true;
            Thread socketClient = new Thread(SocketClientReceive);
            socketClient.IsBackground = true;
            socketClient.Start();
        }

        public void SocketClientReceive()
        {
            while (_isConnected)
            {
                try {
                    _socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, ReceiveCallback, buffer);
                }
                catch (SocketException ex)
                {
                    _isConnected = false;
                }
               
                Thread.Sleep(100);
            }
        }

        public void ReceiveCallback(IAsyncResult ar)
        {
        }
    }

public class SocketClientManager

主要記住的是,客戶端是監聽Socket是固定的,是監聽綁定地址的,每當有新的連接訪問,則開啟新的線程與之進行交互,而客戶端只簡單實現與服務端交互,服務端則只有一個。

Socket的進行發送與接收,一般是通過異步方法BeginReceive和BeginSend進行處理,方法一般帶有回調函數,用於執行操作之後的處理。

還有就是連接的關閉,每關閉一個連接,先要結束在Socket所在的線程方法,我這裡的處理是停止掉死循環的函數調用,每當線程所在函數執行完畢,則線程自動銷毀。之後就是關閉所連接的socket。

下面是我程序的完整實現,為了方便socket的管理,我把服務器的所有與客戶端對話的Socket統一用字典管理,並封裝在SocketInfo的內部類中,消息的發送與接收必須先找到該連接socket。

最後就是界面的調用,完成Socket的網絡消息交互。

下面是具體的實現及源碼:

public class SocketManager
    {
        public Dictionary<string,SocketInfo> _listSocketInfo = null;
        Socket _socket = null;
        public SocketInfo socketInfo = null;
        EndPoint _endPoint = null;
        bool _isListening = false;
        int BACKLOG = 10;

        public delegate void OnConnectedHandler(string clientIP);
        public event OnConnectedHandler OnConnected;
        public delegate void OnReceiveMsgHandler(string ip);
        public event OnReceiveMsgHandler OnReceiveMsg;
        public event OnReceiveMsgHandler OnDisConnected;

        public SocketManager(string ip, int port)
        {
            _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPAddress _ip = IPAddress.Parse(ip);
            _endPoint = new IPEndPoint(_ip, port);
            _listSocketInfo = new Dictionary<string, SocketInfo>();
        }

        public void Start()
        {
            _socket.Bind(_endPoint); //綁定端口
            _socket.Listen(BACKLOG); //開啟監聽
            Thread acceptServer = new Thread(AcceptWork); //開啟新線程處理監聽
            acceptServer.IsBackground = true;
            _isListening = true;
            acceptServer.Start();
        }

        public void AcceptWork()
        {
            while (_isListening)
            {
                Socket acceptSocket = _socket.Accept();
                if (acceptSocket != null && this.OnConnected != null)
                {
                    SocketInfo sInfo = new SocketInfo();
                    sInfo.socket = acceptSocket;
                    _listSocketInfo.Add(acceptSocket.RemoteEndPoint.ToString(), sInfo);
                    OnConnected(acceptSocket.RemoteEndPoint.ToString());
                    Thread socketConnectedThread = new Thread(newSocketReceive);
                    socketConnectedThread.IsBackground = true;
                    socketConnectedThread.Start(acceptSocket);
                }
                Thread.Sleep(200);
            }
        }

        public void newSocketReceive(object obj)
        {
            Socket socket = obj as Socket;
            SocketInfo sInfo = _listSocketInfo[socket.RemoteEndPoint.ToString()];
            sInfo.isConnected = true;
            while (sInfo.isConnected)
            {
                try
                {
                    if (sInfo.socket == null) return;
                    //這裡向系統投遞一個接收信息的請求,並為其指定ReceiveCallBack做為回調函數
                    sInfo.socket.BeginReceive(sInfo.buffer, 0, sInfo.buffer.Length, SocketFlags.None, ReceiveCallBack, sInfo.socket.RemoteEndPoint);
                }
                catch (Exception ex)
                {
                    return;
                }
                Thread.Sleep(100);
            }
        }

        private void ReceiveCallBack(IAsyncResult ar)
        {
            EndPoint ep = ar.AsyncState as IPEndPoint;
            SocketInfo info = _listSocketInfo[ep.ToString()];
            int readCount = 0;
            try
            {
                if (info.socket == null) return;
                readCount = info.socket.EndReceive(ar);
            }catch(Exception ex){
                return;
            }
            if (readCount > 0)
            {
                //byte[] buffer = new byte[readCount];
                //Buffer.BlockCopy(info.buffer, 0, buffer, 0, readCount);
                if (readCount < info.buffer.Length)
                {
                    byte[] newBuffer = new byte[readCount];
                    Buffer.BlockCopy(info.buffer, 0, newBuffer, 0, readCount);
                    info.msgBuffer = newBuffer;
                }
                else
                {
                    info.msgBuffer = info.buffer;
                }
                string msgTip = Encoding.ASCII.GetString(info.msgBuffer);
                if (msgTip == "\0\0\0faild")
                {
                    info.isConnected = false;
                    if (this.OnDisConnected != null) OnDisConnected(info.socket.RemoteEndPoint.ToString());
                    _listSocketInfo.Remove(info.socket.RemoteEndPoint.ToString());
                    info.socket.Close();
                    return;
                }
                if (OnReceiveMsg != null) OnReceiveMsg(info.socket.RemoteEndPoint.ToString());
            }
        }

        public void SendMsg(string text, string endPoint)
        {
            if (_listSocketInfo.Keys.Contains(endPoint) && _listSocketInfo[endPoint] != null)
            {
                _listSocketInfo[endPoint].socket.Send(Encoding.ASCII.GetBytes(text));
            }
        }

        public void Stop()
        {
            _isListening = false;
            foreach (SocketInfo s in _listSocketInfo.Values)
            {
                s.socket.Close();
            }
        }

        public class SocketInfo
        {
            public Socket socket = null;
            public byte[] buffer = null;
            public byte[] msgBuffer = null;
            public bool isConnected = false;

            public SocketInfo()
            {
                buffer = new byte[1024 * 4];
            }
        }
    }

public class SocketServerManager

 

public class SocketClientManager
    {
        public Socket _socket = null;
        public EndPoint endPoint = null;
        public SocketInfo socketInfo = null;
        public bool _isConnected = false;

        public delegate void OnConnectedHandler();
        public event OnConnectedHandler OnConnected;
        public event OnConnectedHandler OnFaildConnect;
        public delegate void OnReceiveMsgHandler();
        public event OnReceiveMsgHandler OnReceiveMsg;

        public SocketClientManager(string ip, int port)
        {
            IPAddress _ip = IPAddress.Parse(ip);
            endPoint = new IPEndPoint(_ip, port);
            _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        }

        public void Start()
        {
            _socket.BeginConnect(endPoint, ConnectedCallback, _socket);
            _isConnected = true;
            Thread socketClient = new Thread(SocketClientReceive);
            socketClient.IsBackground = true;
            socketClient.Start();
        }

        public void SocketClientReceive()
        {
            while (_isConnected)
            {
                SocketInfo info = new SocketInfo();
                try {
                    _socket.BeginReceive(info.buffer, 0, info.buffer.Length, SocketFlags.None, ReceiveCallback, info);
                }
                catch (SocketException ex)
                {
                    _isConnected = false;
                }
               
                Thread.Sleep(100);
            }
        }

        public void ReceiveCallback(IAsyncResult ar)
        {
            socketInfo = ar.AsyncState as SocketInfo;
            if (this.OnReceiveMsg != null) OnReceiveMsg();
        }

        public void ConnectedCallback(IAsyncResult ar)
        {
            Socket socket = ar.AsyncState as Socket;
            if (socket.Connected)
            {
                if (this.OnConnected != null) OnConnected();
            }
            else
            {
                if (this.OnFaildConnect != null) OnFaildConnect();
            }
        }

        public void SendMsg(string msg)
        {
            byte[] buffer = Encoding.ASCII.GetBytes(msg);
            _socket.Send(buffer);
        }

        public class SocketInfo
        {
            public Socket socket = null;
            public byte[] buffer = null;

            public SocketInfo()
            {
                buffer = new byte[1024 * 4];
            }
        }
    }

public class SocketClientManager

具體源碼(.net4.5,vs2013)下載

------------------------------------------分割線------------------------------------------

免費下載地址在 http://linux.linuxidc.com/

用戶名與密碼都是www.linuxidc.com

具體下載目錄在 /2015年資料/1月/29日/C#的Socket簡單實現消息發送/

下載方法見 http://www.linuxidc.com/Linux/2013-07/87684.htm

------------------------------------------分割線------------------------------------------

Copyright © Linux教程網 All Rights Reserved