亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

.net平臺下C#socket通信(中)

2019-11-14 16:21:36
字體:
來源:轉載
供稿:網友

   上篇.net平臺下C#socket通信(上)介紹了socket通信的基本原理及最基本的通信方式。本文在此基礎上就socket通信時經常遇到的問題做一個簡單總結,都是項目中的一些小問題,拿來此處便于下次使用,同時對在使用socket時出現些許問題的同仁們多一個粗淺建議。不足之處請提出,謝謝。

本文主要講述:

1、正常通信中握手建立

2、一對多的通信

3、發送接收數據格式轉換

4、資源釋放

5、開啟并保持服務監聽

 

1、握手建立正常的通信通道

  項目需要通信的雙方(假設是一個上位機、一個下位機)之間需要建立一個穩定的通道,以便進行通信。本項目中具體操作是:上位機作為服務器,下位機作為客戶端,同時制定通信協議。上位機首先打開監聽等待建立通道,下位機主動連接上位機后發送連接成功的信息到上位機,上位機根據通信協議發送數據到下位機,此時通道已經建立。但為了保險起見(同時遵循三次握手),客戶端再次發送數據到上位機告知通道建立完畢。

 

2、一對多通信

  項目需求是一個上位機多個下位機,這就確定了上位機做為服務器端,下位機作為客戶端主動連接服務器。一對一通信時只有一個socket通道,因此無論是上位機還是下位機在發送和接收數據的時候都不會存在數據亂發亂收的情況。一對多意味著上位機和下位機會建立起多個通道,因此在發送數據時需要記錄哪一個下位機處于哪個socket通道中,以便進行邏輯處理。本文處理一對多通信的過程是:

1)首先建立一個對話類session

public class Session    {        public Socket ClientSocket { get; set; }//客戶端的socket        public string ip;//客戶端的ip        public Session(Socket clientSocket)        {            this.ClientSocket = clientSocket;            this.IP = GetIPString();        }        public string GetIPString()        {            string result = ((IPEndPoint)ClientSocket.RemoteEndPoint).Address.ToString();            return result;        }    }

 

2)在服務端socket監聽時:

IPEndPoint loaclEndPoint = new IPEndPoint(IPAddress.Any, Port);            SocketLister = new Socket(AddressFamily.InterNetwork, SocketType.Stream, PRotocolType.Tcp);            SocketLister.Bind(loaclEndPoint);            try            {                SocketLister.Listen(MaxConnection);                while (IsRunning)                {                    ClientSocket = SocketLister.Accept();                    //保存socket                    Session newSession = new Session(ClientSocket);                    lock (sessionLock)                    {                        sessionTable.Add(newSession.IP, newSession);                    }                    SocketConnection socketConnection = new SocketConnection(ClientSocket);                    socketConnection.ReceiveDatagram();//接收數據                }            }            catch (SocketException ex)            {            }



//聲明

public Hashtable sessionTable = new Hashtable ();//包括客戶端會話

private object sessionLock = new object();

 

為了便于理解,把整個服務端socket的建立都寫在上面。

 

3)發送數據到不同的客戶端

Hashtable ht = serverSocket.sessionTable;            foreach (Session session in ht.Values)            {                if (session.IP == "127.0.0.1")//example                {                    SocketConnection socketConnection = new SocketConnection(session.ClientSocket);                    string str = "C300010002D2";                    byte[] sendBytes = StrToHexByte(str);                    socketConnection.Send(sendBytes);                }                           }

SocketConnection類已經被使用多次,寫在下面:

 

public class SocketConnection:IDisposable     {        public ServerSocket Server { get; set; }        public Byte[] MsgBuffer = null;        private int totalLength = 0;        public int CurrentBufferLength;        private Socket _ClientSocket = null;        public Socket ClientSock        {            get{ return this._ClientSocket; }        }        public SocketConnectionType Type { get; private set; }        #region Constructor        public SocketConnection(ServerSocket server, Socket sock)        {            this.Server = server;            this._ClientSocket = sock;            this.Type = SocketConnectionType.Server;        }        public SocketConnection(Socket sock)        {            this._ClientSocket = sock;            this.Type = SocketConnectionType.Client;        }        #endregion         #region Events        public SocketConnectionDelegate OnConnect = null;//是否連接        public SocketConnectionDelegate OnLostConnect = null;//中斷連接        public ReceiveDataDelegate OnReceiveData = null;//接收數據        #endregion         #region Connect        public void Connect(IPAddress ip, int port)        {            this.ClientSock.BeginConnect(ip, port, ConnectCallback, this.ClientSock);        }        private void ConnectCallback(IAsyncResult ar)        {            try            {                Socket handler = (Socket)ar.AsyncState;                handler.EndConnect(ar);                if (OnConnect != null)                {                    OnConnect(this);                }                ReceiveDatagram();            }            catch (SocketException ex)            {            }        }        #endregion        #region Send        public void Send(string data)        {            Send(System.Text.Encoding.UTF8.GetBytes(data));        }        public void Send(byte[] byteData)        {            try            {                int length = byteData.Length;                byte[] head = BitConverter.GetBytes(length);                byte[] data = new byte[head.Length + byteData.Length];                Array.Copy(head, data, head.Length);                Array.Copy(byteData, 0, data, head.Length, byteData.Length);                this.ClientSock.BeginSend(data, 0, data.Length, 0, new AsyncCallback(SendCallback), this.ClientSock);            }            catch (SocketException ex)            {            }        }        private void SendCallback(IAsyncResult ar)        {            try            {                Socket handler = (Socket)ar.AsyncState;                handler.EndSend(ar);            }            catch (SocketException ex)            {            }        }        #endregion        #region ReceiveDatagram             public void ReceiveDatagram()        {            SocketStateObject state = new SocketStateObject();            state.workSocket = _ClientSocket;            _ClientSocket.BeginReceive(state.buffer, 0, SocketStateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);        }        private void ReceiveCallback(IAsyncResult ar)        {            SocketStateObject state = (SocketStateObject)ar.AsyncState;            Socket handler = state.workSocket;            if (handler.Connected)            {                try                {                    state.bytesRead = handler.EndReceive(ar);                    if (state.bytesRead > 0)                    {                        OnDataRecivedCallback(state.buffer, state.bytesRead);                        Array.Clear(state.buffer, 0, state.buffer.Length);                        state.bytesRead = 0;                        handler.BeginReceive(state.buffer, 0, SocketStateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);                    }                    else                    {                        //if (OnDisconnect != null)                        //{                        //    OnDisconnect(this);                        //}                        Dispose();                    }                }                catch (SocketException ex)                { }            }        }        private void ReceiveCallBack00(IAsyncResult ar)        {            try            {                int REnd = _ClientSocket.EndReceive(ar);                if (REnd > 0)                {                    OnDataRecivedCallback(MsgBuffer, REnd );                    Array.Clear(MsgBuffer, 0, MsgBuffer.Length);                    REnd = 0;                    _ClientSocket.BeginReceive(MsgBuffer, 0, MsgBuffer.Length, 0, new AsyncCallback(ReceiveCallBack00), null);                }                else                {                    if (OnLostConnect != null)                    {                        OnLostConnect(this);                    }                    Dispose();                }            }            catch (Exception ex)            {            }        }        private void OnDataRecivedCallback(byte[] data, int length)        {            if (length > 0)            {                if (this.MsgBuffer == null)                {                    byte[] bytelength = new byte[4];                    Array.Copy(data, bytelength, 4);                    this.totalLength = BitConverter.ToInt32(bytelength, 0);                    this.MsgBuffer = new byte[this.totalLength];                    this.CurrentBufferLength = 0;                }                if (this.totalLength > 0)                {                    int offset = 0;                    if (CurrentBufferLength == 0)                    {                        offset = 4;                    }                    if (length + this.CurrentBufferLength >= this.totalLength + offset)                    {                        int len = this.totalLength - CurrentBufferLength;                        Array.Copy(data, offset, this.MsgBuffer, this.CurrentBufferLength, len);                        byte[] tmp = this.MsgBuffer.Clone() as byte[];                        OnReceiveData(new MessageData(this, tmp));                        this.MsgBuffer = null;                        if (length - len - offset > 0)                        {                            tmp = new byte[length - len - offset];                            Array.Copy(data, offset + len, tmp, 0, tmp.Length);                            OnDataRecivedCallback(tmp, tmp.Length);                        }                    }                    else                    {                        Array.Copy(data, offset, this.MsgBuffer, this.CurrentBufferLength, length - offset);                        this.CurrentBufferLength += length - offset;                    }                }                else                {                }            }        }        public void Dispose()        {            try            {                this.ClientSock.Shutdown(SocketShutdown.Both);                this.ClientSock.Close();                this.Server = null;                //if (OnLostConnect != null)                //{                //    OnLostConnect(this);                //}            }            catch            {            }        }        #endregion    }
View Code

 

 

 

3、處理需要發送和接收到的數據

  項目需要是上位機獲取數據進行邏輯處理,然后通過tcp/ip協議發送給下位機,下位機在接收到數據的同時發送確認信息到上位機。項目過程中,上位機在開發過程中需要調試其發送數據、接收數據是否成功,此處借助于USR-  TCP232小工具。但是涉及到一個問題,下位機發送和接收都是byte字節數組,那么開發的上位機應該如何發送和接收數據?在.net平臺下C#socket通信(上),有服務器端的發送和接收函數,發送數據時將要發送的字符串轉換為byte數組,接收時再將字節數組轉換為16進制字符串。如下:

//字節數組轉換為16進制字符串        public string ByteToHexStr(byte[] bytes)        {            string str = "";            if (bytes != null)            {                for (int i = 0; i < bytes.Length; i++)                {                    str += bytes[i].ToString("X2");                }            }            return str;        }        //字符串轉換為16進制byte數組        public byte[] StrToHexByte(string data)        {            data = data.Replace(" ", "");            if ((data.Length % 2) != 0)            {                data += " ";            }            byte[] bytes = new byte[data.Length / 2];            for (int i = 0; i < bytes.Length; i++)            {                 bytes[i] = Convert .ToByte (data.Substring (i * 2,2),16);            }            return bytes;        }

 

4、資源釋放

  開發項目使用平臺是.net,工具vs2010,語言是C#,因為.net有垃圾回收機制,因此在實際開發中產生的托管資源都是系統自動釋放完成。在做本項目時采用winform進行開發的,在此過程中發現一個問題:在關閉Form窗體是運行的系統并沒有完全關閉。查找原因,應該是有資源沒有被釋放。而socket套接字產生的資源恰好是非托管資源,此現象表明系統中有socket資源沒有被完全釋放掉。因此寫了一個資源釋放函數:

public void Dispose()        {            try            {                this.ClientSocket.Shutdown(SocketShutdown.Both);                this.ClientSocket.Dispose();                this.ClientSocket.Close();                this.ClientSocket = null;            }            catch            {            }        }

上述函數的功能就是釋放socket所產生的資源,調用后發現還是存在此問題,幾經調試發現雖然把產生socket通道的監聽客戶端資源釋放完畢,服務器端的serversocket并沒有被釋放,于是有了下一個函數:

public void CloseSocket()        {            if (serverSocket != null)            {                serverSocket.SocketLister.Dispose();                serverSocket.SocketLister = null;                serverSocket.Dispose();//調用的上一個函數                serverSocket = null;            }        }

在上述函數完成后,套接字socket所產生的資源確實被釋放完畢,系統在form關閉后能真正關閉。到此資源好像已經被釋放掉,但緊接著新的問題產生了:

在什么時候什么地方調用釋放資源的函數?

個人簡單看法:

1)系統中止時調用

2)socket通道中斷時調用

 

補充:

5、開啟并保持服務監聽

在socket通信中,服務端的socket監聽其實是需要一直打開并且保持的,只有這樣才能隨時監聽連接的客戶端。項目中示例:

private void button1_Click(object sender, RoutedEventArgs e)        {            Thread thread = new Thread(new ThreadStart(StartServer));            thread.Start();        }public void StartServer()        {            int port = Convert.ToInt32(GetText(this.tbPort));            string ipStr = GetText (this.tbServerIPStr);            if (serverSocket == null)            {                serverSocket = new ServerSocket(port);                serverSocket.Start(ipStr);//            }            else            {                MessageBox.Show("監聽已開啟");            }                 }public void Start(string ipStr)        {            IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, Port);            //IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse(ipStr), Port);            SocketLister = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);            SocketLister.Bind(localEndPoint);            try            {                SocketLister.Listen(MaxConnection);                while (IsRunning)                {                    ClientSocket = SocketLister.Accept();                    //保存socket                    Session newSession = new Session(ClientSocket);                    lock (sessionLock)                    {                        sessionTable.Add(newSession.IP, newSession);                    }                    SocketConnection socketConnection = new SocketConnection(ClientSocket);                    socketConnection.ReceiveDatagram();                }            }            catch (SocketException ex)            {            }        }

解釋:點擊按鈕開啟新的線程thread,執行方法StartServer,StartServer調用方法Start,Start方法中使用死循環開啟并保持監聽。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
97国产真实伦对白精彩视频8| 久久精品国产亚洲7777| 久久久久久久久久久亚洲| 粉嫩av一区二区三区免费野| 免费av一区二区| 欧美电影免费在线观看| 日韩精品极品毛片系列视频| 欧美夜福利tv在线| 日韩在线观看视频免费| 日韩女优人人人人射在线视频| 欧美激情2020午夜免费观看| 亚洲摸下面视频| 欧美性xxxx极品hd欧美风情| 久久精品成人欧美大片| 亚洲国产精品大全| 国产精品久久久久久久一区探花| 亚洲精品国产免费| 亚洲一区二区三区在线免费观看| 欧美激情a在线| 亚洲自拍欧美色图| 97视频免费在线观看| 日韩资源在线观看| 国产精品久久久久久婷婷天堂| 国产精品91久久| 色哟哟网站入口亚洲精品| 中文字幕视频在线免费欧美日韩综合在线看| 大荫蒂欧美视频另类xxxx| 第一福利永久视频精品| 欧美成人精品h版在线观看| 久久久久久尹人网香蕉| 欧美性猛交丰臀xxxxx网站| 美日韩精品视频免费看| 粉嫩老牛aⅴ一区二区三区| 色婷婷久久av| 欧美日韩在线视频首页| 亚洲欧美日韩一区在线| 亚洲第一网中文字幕| 色爱精品视频一区| 欧美国产在线视频| 日韩久久精品成人| 精品久久在线播放| 亚洲成人999| 精品国内亚洲在观看18黄| 91夜夜揉人人捏人人添红杏| 日韩电影免费在线观看| 992tv成人免费影院| 永久555www成人免费| 懂色av一区二区三区| 中文字幕日韩在线观看| 中日韩美女免费视频网址在线观看| 成人在线小视频| 日韩av在线免费播放| 久久亚洲精品视频| 性欧美在线看片a免费观看| 国产精品美女午夜av| 国产在线观看精品一区二区三区| 国产成人一区二区三区电影| 九九热这里只有在线精品视| 国产日韩欧美夫妻视频在线观看| 国产精品视频久久久久| 日韩精品黄色网| 欧美第一黄色网| 色久欧美在线视频观看| 色多多国产成人永久免费网站| 91国内揄拍国内精品对白| 黑人巨大精品欧美一区免费视频| 国产亚洲一区二区在线| 日韩精品在线视频观看| 亚洲精品v天堂中文字幕| 欧美性视频在线| 夜夜嗨av一区二区三区四区| 欧美有码在线观看| 欧美丝袜一区二区| 国产成人在线一区| 亚洲精品视频在线观看视频| 欧美激情女人20p| 国产成人精品久久久| 欧美精品一区二区三区国产精品| 亚洲一区二区三区乱码aⅴ蜜桃女| 日韩av在线免费观看| 亚洲精品免费网站| 亚洲网站在线看| 亚洲精品久久久久久久久| 日本一区二区在线免费播放| 亚洲国产精品va在线观看黑人| 久久人人97超碰精品888| 性欧美xxxx| 蜜月aⅴ免费一区二区三区| 91日韩在线视频| 日本欧美一二三区| 久久99国产精品久久久久久久久| 国产亚洲欧美日韩一区二区| 97免费中文视频在线观看| 视频在线一区二区| 成人免费网视频| 亚洲欧美国产va在线影院| 久久免费视频这里只有精品| 97精品视频在线观看| 欧美性xxxx极品hd满灌| 久久久久久久一| 亚洲成人久久久久| 日韩亚洲精品电影| 亚洲xxx视频| 久久久久国产精品免费网站| 亚洲第一色在线| 国产欧洲精品视频| 日韩美女在线观看| 97精品国产91久久久久久| 成人亲热视频网站| 91色在线视频| 久久久久久18| 北条麻妃一区二区三区中文字幕| 久久全球大尺度高清视频| 91精品久久久久久久久久入口| 一本一本久久a久久精品牛牛影视| 亚洲成人999| 51视频国产精品一区二区| 国产欧美日韩丝袜精品一区| 成人在线一区二区| 激情成人中文字幕| 国产精品欧美激情| 亚洲精品免费一区二区三区| 亚洲高清在线观看| 中文字幕视频在线免费欧美日韩综合在线看| 大胆欧美人体视频| 国产欧美精品va在线观看| 亚洲欧美在线免费| 亚洲欧美综合v| 97免费中文视频在线观看| 92国产精品视频| 亚洲欧洲国产伦综合| 国产不卡av在线| 人人爽久久涩噜噜噜网站| 久久全国免费视频| 久久久久成人网| 色偷偷av一区二区三区乱| 97在线看福利| 青青久久aⅴ北条麻妃| 亚洲影视九九影院在线观看| 91在线视频精品| 亚洲一区制服诱惑| 国产一区二区三区18| 国产一区二区三区直播精品电影| 亚洲成年人影院在线| 午夜精品视频在线| 国产精品色午夜在线观看| 伦伦影院午夜日韩欧美限制| 亚州精品天堂中文字幕| 亚洲第一天堂av| 91日韩在线播放| 欧美交受高潮1| 亚洲精品免费在线视频| 国产欧美一区二区白浆黑人| 中文字幕av一区二区三区谷原希美| 日韩av不卡在线| 中文字幕日韩欧美| 高清一区二区三区四区五区| 日韩欧美在线观看视频| 亚洲女人天堂色在线7777| 国内成人精品视频| 国产精品ⅴa在线观看h| 亚洲第一二三四五区| 欧美精品亚州精品| 日韩影视在线观看|