Java培訓(xùn)中 精點、難點知識總結(jié)匯總
Socket不僅在聊天應(yīng)用程序中需要用到,而且對于學(xué)習(xí)Asp.net也非常有幫助。你懂得!
實現(xiàn)服務(wù)端和客戶端互發(fā)信息,以及服務(wù)端向多個客戶端發(fā)送信息。
服務(wù)端代碼1:
- public Form1()
- {
- InitializeComponent();
- Control.CheckForIllegalCrossThreadCalls = false;
- }
- //創(chuàng)建監(jiān)聽用的socket
- private void btnStartMonitor_Click(object sender, EventArgs e)
- {
- //監(jiān)聽的ip地址
- IPAddress ip = IPAddress.Parse(txtIP.Text);
- //監(jiān)聽的ip地址和端口號
- IPEndPoint point = new IPEndPoint(ip, int.Parse(txtPortNumber.Text));
- //監(jiān)聽用的socket
- Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
- //通常每個套接字地址(協(xié)議/網(wǎng)絡(luò)地址/端口)只允許使用一次
- //綁定監(jiān)聽的ip地址和端口號
- socket.Bind(point);
- //監(jiān)聽端口 監(jiān)聽隊列的長度:同一個時間等待的個數(shù)。
- socket.Listen(10);
- //點擊之后,禁用掉按鈕
- btnStartMonitor.Enabled = false;
- //提示用戶程序開始運行了
- ShowMsg("開始運行了...");
- //監(jiān)聽端口,如果有客戶端連接,創(chuàng)建通信用socket
- //阻塞窗體的運行
- //Socket connSocket = socket.Accept();
- //用線程來解決窗體假死的問題
- Thread th = new Thread(Listen);
- th.IsBackground = true;//后臺線程
- th.Start(socket);
- }
- //監(jiān)聽是否有客戶端連接
- void Listen(object o)
- {
- //監(jiān)聽用的socket
- Socket socket = o as Socket;
- //監(jiān)聽端口
- Socket connSocket = socket.Accept();
- //顯示遠(yuǎn)程連接的IP地址和端口號
- ShowMsg(connSocket.RemoteEndPoint.ToString());
- }
- //在文本框顯示信息
- void ShowMsg(string msg)
- {
- txtShowMessage.AppendText(msg + "\r\n");
- }
復(fù)制代碼
以上代碼只能讓一個客戶端連接服務(wù)端,弊端。
服務(wù)端代碼2完善——循環(huán)接收客戶端連接:
- //監(jiān)聽是否有客戶端連接
- void Listen(object o)
- {
- //監(jiān)聽用的socket
- Socket socket = o as Socket;
- //可以不停地接受客戶端的連接
- while (true)
- {
- //負(fù)責(zé)通信用的socket
- Socket connSocket = socket.Accept();
- //顯示遠(yuǎn)程連接的IP地址和端口號
- ShowMsg(connSocket.RemoteEndPoint.ToString());
- //本機(jī)的IP地址和端口號
- //connSocket.LocalEndPoint
- //接收數(shù)據(jù)
- byte[] buffer = new byte[1024 * 1023];
- //接收數(shù)據(jù),把數(shù)據(jù)發(fā)到buffer中
- //num是實際接收到的字節(jié)個數(shù)
- int num=connSocket.Receive(buffer);
- //把實際有效的字節(jié)轉(zhuǎn)換成字符串
- string str = Encoding.UTF8.GetString(buffer, 0, num);
- ShowMsg(str);
- }
- }
復(fù)制代碼
服務(wù)端代碼3完善——循環(huán)接收消息:
- //監(jiān)聽是否有客戶端連接
- void Listen(object o)
- {
- //監(jiān)聽用的socket
- Socket socket = o as Socket;
- //可以不停地接受客戶端的連接
- while (true)
- {
- //負(fù)責(zé)通信用的socket
- Socket connSocket = socket.Accept();
- //顯示遠(yuǎn)程連接的IP地址和端口號
- ShowMsg(connSocket.RemoteEndPoint.ToString());
- //本機(jī)的IP地址和端口號
- //connSocket.LocalEndPoint
- //循環(huán)接收消息
- while(true)
- {
- //接收數(shù)據(jù)
- byte[] buffer = new byte[1024 * 1023];
- //接收數(shù)據(jù),把數(shù)據(jù)發(fā)到buffer中
- //num是實際接收到的字節(jié)個數(shù)
- int num=connSocket.Receive(buffer);
- //把實際有效的字節(jié)轉(zhuǎn)換成字符串
- string str = Encoding.UTF8.GetString(buffer, 0, num);
- ShowMsg(str);
- }
- }
- }
復(fù)制代碼
服務(wù)端代碼4完善——循環(huán)多個客戶端并接收信息:
- //監(jiān)聽是否有客戶端連接
- void Listen(object o)
- {
- //監(jiān)聽用的socket
- Socket socket = o as Socket;
- //可以不停地接受客戶端的連接
- while (true)
- {
- //負(fù)責(zé)通信用的socket
- Socket connSocket = socket.Accept();
- //顯示遠(yuǎn)程連接的IP地址和端口號
- ShowMsg(connSocket.RemoteEndPoint.ToString());
- //本機(jī)的IP地址和端口號
- //connSocket.LocalEndPoint
- //線程接收信息
- Thread th = new Thread(RecMsg);
- th.IsBackground = true;
- th.Start(connSocket);
- }
- }
- //接收信息
- void RecMsg(object o)
- {
- //通信用的socket
- Socket connSocket = o as Socket;
- //可以不停地接受客戶端的內(nèi)容
- while (true)
- {
- //接受數(shù)據(jù)
- byte[] buffer = new byte[1024 * 1024];
- //接受數(shù)據(jù),把數(shù)據(jù)發(fā)到buffer中
- //num就是實際接受到的字節(jié)個數(shù)
- int num = connSocket.Receive(buffer);
- //當(dāng)telnet關(guān)閉,會不停的發(fā)送空(0)字節(jié)
- //把實際有效的字節(jié)轉(zhuǎn)化成字符串
- string str = Encoding.UTF8.GetString(buffer, 0, num);
- ShowMsg(connSocket.RemoteEndPoint.ToString() + ":" + str);
- }
- }
- }
復(fù)制代碼
服務(wù)端代碼5完善——限制客戶端連接數(shù):
- //限制連接客戶端的個數(shù)
- int count=0;
- void Listen(object o)
- {
- //監(jiān)聽用的socket
- Socket socket = o as Socket;
- //可以不停地接受客戶端的連接
- while (count<1000)
- {
- //負(fù)責(zé)通信用的socket
- Socket connSocket = socket.Accept();
- //顯示遠(yuǎn)程連接的IP地址和端口號
- ShowMsg(connSocket.RemoteEndPoint.ToString());
- //本機(jī)的IP地址和端口號
- //connSocket.LocalEndPoint
- //線程接收信息
- Thread th = new Thread(RecMsg);
- th.IsBackground = true;
- th.Start(connSocket);
- }
- }
復(fù)制代碼
服務(wù)端代碼6完善——解決“當(dāng)tenet關(guān)閉,會不停地發(fā)送空(0)字節(jié)”:
- //接收信息
- void RecMsg(object o)
- {
- //通信用的socket
- Socket connSocket = o as Socket;
- //可以不停地接受客戶端的內(nèi)容
- while (true)
- {
- //接受數(shù)據(jù)
- byte[] buffer = new byte[1024 * 1024];
- //接受數(shù)據(jù),把數(shù)據(jù)發(fā)到buffer中
- //num就是實際接受到的字節(jié)個數(shù)
- int num = connSocket.Receive(buffer);
- //當(dāng)telnet關(guān)閉,會不停的發(fā)送空(0)字節(jié)
- //當(dāng)telnet關(guān)閉,會不停的發(fā)送(0)個字節(jié) 客戶端斷開
- if (num == 0)
- {
- ShowMsg(connSocket.RemoteEndPoint.ToString() + ":退出");
- connSocket.Shutdown(SocketShutdown.Receive);
- connSocket.Close();
- break;
- }
- //把實際有效的字節(jié)轉(zhuǎn)化成字符串
- string str = Encoding.UTF8.GetString(buffer, 0, num);
- ShowMsg(connSocket.RemoteEndPoint.ToString() + ":" + str);
- }
- }
- }
復(fù)制代碼
客戶端代碼1:
- public Form1()
- {
- InitializeComponent();
- Control.CheckForIllegalCrossThreadCalls = false;
- }
- //連接服務(wù)端和發(fā)送信息都要用到同一個socket,將其定義到外邊
- Socket socket;
- //連接服務(wù)端
- private void btnConnect_Click(object sender, EventArgs e)
- {
- //客戶端連接服務(wù)器的ip地址
- IPAddress ip = IPAddress.Parse(txtIP.Text);
- //客戶端連接的服務(wù)器的ip地址和端口號
- IPEndPoint point = new IPEndPoint(ip, int.Parse(txtPortNumber.Text));
- //創(chuàng)建連接使用的socket
- socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
- try
- {
- //連接聊天服務(wù)器
- //服務(wù)器沒開報錯
- //由于目標(biāo)計算機(jī)積極拒絕,無法連接。
- socket.Connect(point);
- ShowMsg("連接成功");
- }
- catch (Exception ex)
- {
- ShowMsg(ex.Message);
- }
- }
- void ShowMsg(string msg)
- {
- txtShowMessage.AppendText(msg + "\r\n");
- }
- //發(fā)送消息
- private void btnSendMessage_Click(object sender, EventArgs e)
- {
- if (socket != null)
- {
- byte[] buffer = Encoding.UTF8.GetBytes(txtInputMessage.Text);
- socket.Send(buffer);
- }
- else
- {
- MessageBox.Show("請先連接");
- }
- }
復(fù)制代碼
客戶端代碼7完善——服務(wù)端知道客戶端關(guān)閉的消息:
- //接收信息
- void RecMsg(object o)
- {
- //通信用的socket
- Socket connSocket = o as Socket;
- //可以不停地接受客戶端的內(nèi)容
- while (true)
- {
- //接受數(shù)據(jù)
- byte[] buffer = new byte[1024 * 1024];
- //接受數(shù)據(jù),把數(shù)據(jù)發(fā)到buffer中
- //num就是實際接受到的字節(jié)個數(shù)
- int num = -1;
- try
- {
- //遠(yuǎn)程主機(jī)強(qiáng)迫關(guān)閉了一個現(xiàn)有的連接。 當(dāng)客戶端關(guān)閉,服務(wù)端未關(guān)閉時,報錯。
- num = connSocket.Receive(buffer);
- //當(dāng)telnet關(guān)閉,會不停的發(fā)送(0)個字節(jié) 客戶端斷開
- if (num == 0)
- {
- ShowMsg(connSocket.RemoteEndPoint.ToString() + ":退出");
- connSocket.Shutdown(SocketShutdown.Receive);
- connSocket.Close();
- break;
- }
- //把實際有效的字節(jié)轉(zhuǎn)化成字符串
- string str = Encoding.UTF8.GetString(buffer, 0, num);
- ShowMsg(connSocket.RemoteEndPoint.ToString() + ":" + str);
- }
- catch (Exception ex)
- {
- ShowMsg(ex.Message);
- //出現(xiàn)異常,跳出循環(huán)
- break;
- }
- }
- }
復(fù)制代碼
服務(wù)端代碼8完善——服務(wù)端給客戶端發(fā)送消息:
- //發(fā)送消息
- private void btnSendMessage_Click(object sender, EventArgs e)
- {
- if (connSocket!=null)
- {
- byte[] buffer = Encoding.UTF8.GetBytes(txtInputMessage.Text);
- try
- {
- connSocket.Send(buffer);
- }
- catch (Exception ex)
- {
- ShowMsg(ex.Message);
- }
- }
- }
復(fù)制代碼
客戶端代碼2完善——客戶端接收服務(wù)端發(fā)送的消息:
- //接收消息
- void RecMsg()
- {
- while (true)
- {
- byte[] buffer = new byte[1024 * 1024];
- try
- {
- int num = socket.Receive(buffer);
- string str = Encoding.UTF8.GetString(buffer, 1, num );
- ShowMsg(str);
- }
- catch (Exception ex)
- {
- ShowMsg(ex.Message);
- break;
- }
- }
- }
- //由于接收消息是一個死循環(huán),需要用到線程
- //線程接受消息
- Thread th = new Thread(RecMsg);
- th.IsBackground = true;
- th.Start();
復(fù)制代碼
服務(wù)端代碼9完善——服務(wù)端給指定客戶端發(fā)送消息:
- //存儲通信用的socket字典
- Dictionary<string, Socket> dic = new Dictionary<string, Socket>();
- //限制連接客戶端的個數(shù)
- int count = 0;
- //監(jiān)聽是否有客戶端連接
- void Listen(object o)
- {
- //監(jiān)聽用的socket
- Socket socket = o as Socket;
- //可以不停地接受客戶端的連接
- while (count < 100)
- {
- count++;
- //監(jiān)聽端口,如果有客戶端連接,創(chuàng)建通信用socket
- Socket connSocket = socket.Accept();
- //顯示遠(yuǎn)程連接的IP地址和端口號
- ShowMsg(connSocket.RemoteEndPoint.ToString());
- //本機(jī)的IP地址和端口號
- //connSocket.LocalEndPoint
- //保存當(dāng)前登錄的客戶端的socket
- string ipport = connSocket.RemoteEndPoint.ToString();
- cboUser.Items.Add(ipport);
- dic.Add(ipport, connSocket);
- //線程接收信息
- Thread th = new Thread(RecMsg);
- th.IsBackground = true;
- th.Start(connSocket);
- }
- }
- //發(fā)送消息
- private void btnSendMessage_Click(object sender, EventArgs e)
- {
- //獲取下拉框中選擇的ip和端口號
- string ipport = cboUser.Text;
- if (!string.IsNullOrEmpty(ipport))
- {
- byte[] buffer = Encoding.UTF8.GetBytes(txtInputMessage.Text);
- try
- {
- //根據(jù)key獲得socket
- Socket connSocket = dic[ipport];
- connSocket.Send(buffer);
- }
- catch (Exception ex)
- {
- ShowMsg(ex.Message);
- }
- }
- else
- {
- MessageBox.Show("請選擇客戶端");
- }
- }
復(fù)制代碼
Java培訓(xùn)學(xué)院始終認(rèn)為你將會是最優(yōu)秀的存在,你就是最棒的,看好你,加油!??!