Socket客戶端

這次寫一下Socket客戶端,

在此之前先分享一下我找到的一張圖

這張圖和之前我畫的服務器端和客戶端之間的通信基本相同,不過這張圖更可信一點。

下面就來寫一下左面的客戶端


下面直接貼代碼了

 public MainFrm()
        {
            InitializeComponent();
        }

        private Socket socket;
        private void btnConn_Click(object sender, EventArgs e)
        {
            //創建一個Socket對象
            Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            txtMsgShow("正在努力鏈接服務器端。。。。");
            //等待期間需要處理異常
            try
            {
                //連接服務器
                clientSocket.Connect(IPAddress.Parse(txtIP.Text), int.Parse(txtPort.Text));
            }
            catch (Exception)
            {
                Thread.Sleep(3000);
                MessageBox.Show("連接失敗!請重新連接。。。");
                return;
            }
            
             socket = clientSocket;
             txtMsgShow(string.Format("{0}服務器端已經連接成功\r\n",socket.RemoteEndPoint)); 
            //開啓另一個線程接收數據
             ThreadPool.QueueUserWorkItem(new WaitCallback(ReceiveMsgFromServer), socket);           
        }

        //接收數據
        private void ReceiveMsgFromServer(object state)
        {
            Socket socket = (Socket)state;
            int count=0;
            //1M緩存區
            byte[] recByte = new byte[1024 * 1024];
            while (true)
            {
                try
                {
                    count = socket.Receive(recByte, 0, recByte.Length, SocketFlags.None);
                }
                catch
                {
                    txtMsgShow(string.Format("來自服務器端的消息:對方非正常退出了\r\n{0}", txtMsg.Text));
                    StopConnect();
                    return;
                }
   
                //判斷一下服務器端是否正常退出
                //正常退出
                if (count <= 0) 
                {
                    txtMsgShow(string.Format("來自服務器端的消息:對方正常退出了{0}",txtMsg.Text));
                    StopConnect();
                    return;
                }


                //然後將緩存區中的byte轉換成string在msg中顯示出來
                string str = Encoding.Default.GetString(recByte, 0, count);
                txtMsgShow(string.Format("來自服務器端的消息:{1}\r\n{0}", txtMsg.Text, str));
            }
            
        }



        //發送數據
        private void btnSend_Click(object sender, EventArgs e)
        {
            if (socket.Connected)
            {
                byte[] sendByte = Encoding.Default.GetBytes(txtSend.Text);
                socket.Send(sendByte,0,sendByte.Length,SocketFlags.None);
                txtMsgShow(string.Format("你發送的消息:{0}\r\n{1}", txtSend.Text,txtMsg.Text));
                //清空發送欄
                txtSend.Text = "";
            }
        }

        //用於顯示接收連接情況
        private void txtMsgShow(string str) 
        {
            if (txtMsg.InvokeRequired)
            {
                txtMsg.Invoke(new Action<string>((s) => {
                    txtMsg.Text = s;
                }),str);
            }
            else 
            {
                txtMsg.Text = str;
            }
        }

        //關閉連接
        private void StopConnect()
        {
            try
            {
                if (socket.Connected)
                {
                    socket.Shutdown(SocketShutdown.Both);
                    socket.Close(100);
                }
            }
                //不管了
            catch
            {
                              
            }
            
        }

        private void MainFrm_FormClosing(object sender, FormClosingEventArgs e)
        {
            StopConnect();
        }
    }

這裏有兩點需要注意

(1)客戶端的Socket會自動分配一個隨機的端口,所以在IP一欄填服務器主機的IP就行

(2)如果你是調試進行的測試,在關閉客戶端時,會報一個創建句柄出錯的異常,

是這句話的異常

 txtMsgShow(string.Format("來自服務器端的消息:對方非正常退出了\r\n{0}", txtMsg.Text));
因爲你已經關閉窗體,所以不可能再在txtbox中顯示消息。

不過你可以不用理會這個異常,因爲,真正使用exe時,窗體已經關閉,不可能再有什麼異常。



結合之前寫過的服務器端就可以互相通信了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章