C#實現伺服器和客戶端之間通訊
阿新 • • 發佈:2018-12-24
TCP 套接字程式設計
伺服器端實現步驟:
1、使用Socket類建立套接字。
2、利用Bind方法將建立的套接字繫結到指定的地址結構。
3、利用Listen方法設定套接字為監聽模式,使得伺服器進入被動開啟狀態。
4、接受客戶端的連線請求。
5、接收、應答客戶端的資料請求。
6、終止連線。
客戶端實現步驟:
1、使用Socket類建立套接字。
2、呼叫Connect方法建立一個與TCP伺服器的連線。
3、傳送資料請求,接受伺服器的資料應答。
4、終止連線。
一對一:客戶端程式碼:
using System; using System.Net; using System.Net.Sockets; using System.Threading; using System.Text; namespace Client { class Problem { private static byte[] result = new byte[1024 * 1024]; static Socket ClientSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp); static void Main(string[] args) { int Port = 8222; IPAddress IP = IPAddress.Parse("127.0.0.1"); try { Console.WriteLine("連線伺服器成功!!!"); ClientSocket.Connect(new IPEndPoint(IP,Port)); } catch(Exception ex) { Console.WriteLine("連線伺服器失敗,按回車鍵退出!"); return; } for(int i=0;i<10;i++) { try { Thread.Sleep(2000); int ReceiveLength = ClientSocket.Receive(result); Console.WriteLine("接收伺服器訊息:{0}",Encoding.ASCII.GetString(result,0,ReceiveLength)); Console.WriteLine("向伺服器傳送訊息:"); string sb = Console.ReadLine(); string SendMessage = "向伺服器傳送訊息:" + DateTime.Now + "\n" + sb; ClientSocket.Send(Encoding.ASCII.GetBytes(SendMessage)); } catch(Exception ex) { ClientSocket.Shutdown(SocketShutdown.Both); ClientSocket.Close(); } } Console.WriteLine("訊息傳送完畢!!!"); Console.WriteLine(); } } }
using System; using System.Net; using System.Net.Sockets; using System.Threading; using System.Text; namespace Server { class Program { public static void ListenClientConnect() { while(true) { Socket ClientSocket = ServerSocket.Accept();//send Console.WriteLine("向客戶端傳送訊息:"); string sb = Console.ReadLine(); ClientSocket.Send(Encoding.ASCII.GetBytes("Server Say Hello:"+sb)); Thread thread = new Thread(ReceiveMessage); thread.Start(ClientSocket); } } public static void ReceiveMessage(Object ClientSocket) { Socket MyClientSocket = (Socket)ClientSocket; while(true) { try { int ReceiveNum = MyClientSocket.Receive(result); Console.WriteLine("接受客戶端{0}訊息{1}:" ,MyClientSocket.RemoteEndPoint.ToString(), Encoding.ASCII.GetString(result,0,ReceiveNum)); Console.WriteLine("向客戶端傳送訊息:"); string sb = Console.ReadLine(); MyClientSocket.Send(Encoding.ASCII.GetBytes(sb)); } catch(Exception ex) { Console.WriteLine("404 Not found!!!"); MyClientSocket.Shutdown(SocketShutdown.Both); MyClientSocket.Close(); } } } private static byte[] result = new byte[1024 * 1024]; static Socket ServerSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp); static void Main(String[] args) { try { int Port = 8222; IPAddress IP = IPAddress.Parse("127.0.0.1"); ServerSocket.Bind(new IPEndPoint(IP, Port)); ServerSocket.Listen(10); Console.WriteLine("啟動監聽{0}成功",ServerSocket.LocalEndPoint.ToString()); Thread thread = new Thread(ListenClientConnect); thread.Start(); Thread.Sleep(2000); } catch(Exception ex) { throw ex; } } } }
一對多:
服務端程式碼:
using System; using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.Threading; using System.Text; using System.Linq; namespace Server { class Program { public static void ListenConnection() { Socket ConnectionSocket = null; while(true) { try { ConnectionSocket = ServerSocket.Accept(); } catch(Exception ex) { Console.WriteLine("監聽套接字異常{0}",ex.Message); break; } //獲取客戶端埠號和IP IPAddress ClientIP=(ConnectionSocket.RemoteEndPoint as IPEndPoint).Address; int ClientPort = (ConnectionSocket.RemoteEndPoint as IPEndPoint).Port; string SendMessage = "連線伺服器成功\r\n" + "本地IP:" + ClientIP + ",本地埠:" + ClientPort.ToString(); //Console.WriteLine(SendMessage); ConnectionSocket.Send(Encoding.UTF8.GetBytes(SendMessage)); string remotePoint = ConnectionSocket.RemoteEndPoint.ToString(); Console.WriteLine("成功與客戶端{0}建立連線!\t\n", remotePoint); ClientInformation.Add(remotePoint, ConnectionSocket); Thread thread = new Thread(ReceiveMessage); thread.IsBackground = true; thread.Start(ConnectionSocket); } } public static void ReceiveMessage(Object SocketClient) { Socket ReceiveSocket = (Socket)SocketClient; while(true) { byte[] result = new byte[1024 * 1024]; try { IPAddress ClientIP = (ReceiveSocket.RemoteEndPoint as IPEndPoint).Address; int ClientPort = (ReceiveSocket.RemoteEndPoint as IPEndPoint).Port; int ReceiveLength = ReceiveSocket.Receive(result); string ReceiveMessage = Encoding.UTF8.GetString(result, 0, ReceiveLength); Console.WriteLine("接收客戶端:" + ReceiveSocket.RemoteEndPoint.ToString()+ "時間:"+DateTime.Now.ToString()+"\r\n"+"訊息:"+ReceiveMessage+"\r\n\n"); foreach(string key in new List<string>(ClientInformation.Keys)) { string s = ReceiveSocket.RemoteEndPoint.ToString(); if(key!=s) { Socket socket = ClientInformation[key]; Console.WriteLine("向客戶端{0}傳送訊息:", key); socket.Send(Encoding.UTF8.GetBytes(ReceiveMessage)); } } //Console.WriteLine("向客戶端{0}傳送訊息:", ReceiveSocket.RemoteEndPoint.ToString()); //string sb = Console.ReadLine(); //ReceiveSocket.Send(Encoding.UTF8.GetBytes(sb)); } catch(Exception ex) { Console.WriteLine("監聽出現異常!!!"); Console.WriteLine("客戶端" + ReceiveSocket.RemoteEndPoint + "已經連線中斷" + "\r\n" + ex.Message + "\r\n" + ex.StackTrace + "\r\n"); foreach(string key in new List<string>(ClientInformation.Keys)) { string s = ReceiveSocket.RemoteEndPoint.ToString(); if (key.Equals(s)) { ClientInformation.Remove(key); } } ReceiveSocket.Shutdown(SocketShutdown.Both); ReceiveSocket.Close(); break; } } } //private static byte[] result = new byte[1024]; //List<Socket> list = new List<Socket>(); static Dictionary<string, Socket> ClientInformation = new Dictionary<string, Socket> { }; static Socket ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); static void Main(String[] args) { try { int Port = 8333; IPAddress IP = IPAddress.Parse("127.0.0.1"); ServerSocket.Bind(new IPEndPoint(IP, Port)); ServerSocket.Listen(10); Console.WriteLine("啟動監聽成功!"); Console.WriteLine("監聽本地{0}成功", ServerSocket.LocalEndPoint.ToString()); Thread ThreadListen = new Thread(ListenConnection); ThreadListen.IsBackground = true; ThreadListen.Start(); Thread.Sleep(2000); } catch(Exception ex) { Console.WriteLine("監聽異常!!!"); ServerSocket.Shutdown(SocketShutdown.Both); ServerSocket.Close(); } Console.ReadKey(); Console.WriteLine("監聽完畢,按任意鍵退出!"); } } }
using System; using System.Net; using System.Net.Sockets; using System.Threading; using System.Text; namespace Client { class Problem { private static byte[] result = new byte[1024 * 1024]; static Socket ClientSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp); public static void ReceiveMessage() { while(true) { try { int ReceiveLength = ClientSocket.Receive(result); Console.WriteLine("接收伺服器訊息:{0}", Encoding.UTF8.GetString(result, 0, ReceiveLength)); } catch(Exception ex) { Console.WriteLine("出現異常了!!!"); Console.WriteLine(ex.Message); ClientSocket.Shutdown(SocketShutdown.Both); ClientSocket.Close(); break; } } } static void Main(string[] args) { int Port = 8333; IPAddress IP = IPAddress.Parse("127.0.0.1"); try { ClientSocket.Connect(new IPEndPoint(IP,Port)); Thread thread = new Thread(ReceiveMessage); thread.Start(); Thread.Sleep(2000); } catch(Exception ex) { Console.WriteLine("連線伺服器失敗,按回車鍵退出!"); return; } Console.WriteLine("連線伺服器成功!!!"); //int ReceiveLength = ClientSocket.Receive(result); //Console.WriteLine("接收伺服器訊息:{0}", Encoding.UTF8.GetString(result, 0, ReceiveLength)); while (true) { try { Thread.Sleep(2000); Console.WriteLine("向伺服器傳送訊息:"); string sb = Console.ReadLine(); string Client = ClientSocket.RemoteEndPoint.ToString(); string SendMessage = "接收客戶端" + Client + "訊息:" + DateTime.Now + "\n" + sb; ClientSocket.Send(Encoding.ASCII.GetBytes(sb)); } catch(Exception ex) { ClientSocket.Shutdown(SocketShutdown.Both); ClientSocket.Close(); break; } } Console.WriteLine("訊息傳送完畢!!!"); Console.ReadLine(); } } }
下面是一對多的使用窗體介面顯示的程式碼以及顯示效果:
客戶端程式碼:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Net.Sockets; using System.Net; using System.Threading; using System.IO; namespace ClientForm { public partial class Form1 : Form { private byte[] result = new byte[1024 * 1024]; private Socket ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); public Form1() { InitializeComponent(); TextBox.CheckForIllegalCrossThreadCalls = false; } private void Form1_Load(object sender, EventArgs e) { ; } private void textBox1_TextChanged(object sender, EventArgs e)//輸入訊息 { //; string str = Console.ReadLine(); textBox1.Text += str; } private void textBox2_TextChanged(object sender, EventArgs e)//ip { ; } private void textBox3_TextChanged(object sender, EventArgs e)//port { ; } private void button1_Click(object sender, EventArgs e)//傳送訊息 { try { //Thread.Sleep(2000); richTextBox1.Text += "向伺服器傳送訊息:\r\n"; richTextBox1.Text += textBox1.Text + "\r\n"; string sb = textBox1.Text; string Client = ClientSocket.RemoteEndPoint.ToString(); string SendMessage = "接收客戶端" + Client + "訊息:" + DateTime.Now + "\r\n" + sb + "\r\n"; ClientSocket.Send(Encoding.UTF8.GetBytes(sb)); textBox1.Clear(); } catch (Exception ex) { richTextBox1.Text += "伺服器可能已經關閉!\r\n"; ClientSocket.Shutdown(SocketShutdown.Both); ClientSocket.Close(); } } private void button2_Click(object sender, EventArgs e)//連線伺服器 { int Port = Convert.ToInt32(textBox3.Text); IPAddress IP = IPAddress.Parse((string)textBox2.Text); try { ClientSocket.Connect(new IPEndPoint(IP, Port)); richTextBox2.Text += "連線伺服器成功!\r\n"; Thread thread = new Thread(ReceiveMessage); thread.IsBackground = true; thread.Start(); } catch (Exception ex) { richTextBox2.Text += "連線伺服器失敗!\r\n"; return; } } private void label1_Click(object sender, EventArgs e) { ; } private void label2_Click(object sender, EventArgs e) { ; } private void richTextBox1_TextChanged(object sender, EventArgs e)//顯示傳送的訊息 { ; } private void richTextBox2_TextChanged(object sender, EventArgs e)//顯示接收的訊息 { ; } private void ReceiveMessage() { while (true) { try { int ReceiveLength = ClientSocket.Receive(result); richTextBox2.Text += "接收伺服器訊息:\r\n"; string str = Encoding.UTF8.GetString(result, 0, ReceiveLength)+"\r\n"; richTextBox2.Text += str; } catch (Exception ex) { richTextBox2.Text += "接收訊息失敗!\r\n"; ClientSocket.Shutdown(SocketShutdown.Both); ClientSocket.Close(); break; } } } } }
服務端程式碼:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Net.Sockets; using System.Net; using System.Threading; using System.IO; using System.Threading; namespace ServerForm { public partial class Form1 : Form { private byte[] result = new byte[1024 * 1024]; private Socket ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); private Dictionary<string, Socket> ClientInformation = new Dictionary<string, Socket> { }; public Form1() { InitializeComponent(); TextBox.CheckForIllegalCrossThreadCalls = false; //在多執行緒程式中,新建立的執行緒不能訪問UI執行緒建立的視窗控制元件 //如果需要訪問視窗控制元件則可以如此設定 } private void label1_Click(object sender, EventArgs e)//ip { } private void label2_Click(object sender, EventArgs e)//Port { } private void label3_Click(object sender, EventArgs e)//線上列表 { } private void richTextBox1_TextChanged(object sender, EventArgs e)//顯示客戶端之間/客戶端訊息 { } private void richTextBox2_TextChanged(object sender, EventArgs e)//顯示連線成功或者掉線的客戶端 { } private void richTextBox3_TextChanged(object sender, EventArgs e)//顯示線上列表 { } private void textBox1_TextChanged(object sender, EventArgs e)//IP { } private void textBox2_TextChanged(object sender, EventArgs e)//Port { } private void button1_Click(object sender, EventArgs e)//啟動服務 { try { int Port = Convert.ToInt32(textBox2.Text); IPAddress IP = IPAddress.Parse((string)textBox1.Text); ServerSocket.Bind(new IPEndPoint(IP, Port)); ServerSocket.Listen(10); richTextBox2.Text += "啟動監聽成功!\r\n"; richTextBox2.Text += "監聽本地" + ServerSocket.LocalEndPoint.ToString() + "成功\r\n"; Thread ThreadListen = new Thread(ListenConnection); ThreadListen.IsBackground = true; ThreadListen.Start(); Thread.Sleep(2000); } catch(Exception ex) { richTextBox2.Text += "監聽異常!!!\r\n"; ServerSocket.Shutdown(SocketShutdown.Both); ServerSocket.Close(); } } private void ListenConnection() { Socket ConnectionSocket = null; while (true) { try { ConnectionSocket = ServerSocket.Accept(); } catch (Exception ex) { richTextBox2.Text += "監聽套接字異常" + ex.Message; //Console.WriteLine("監聽套接字異常{0}", ex.Message); break; } //獲取客戶端埠號和IP IPAddress ClientIP = (ConnectionSocket.RemoteEndPoint as IPEndPoint).Address; int ClientPort = (ConnectionSocket.RemoteEndPoint as IPEndPoint).Port; string SendMessage = "本地IP:" + ClientIP + ",本地埠:" + ClientPort.ToString(); ConnectionSocket.Send(Encoding.UTF8.GetBytes(SendMessage)); string remotePoint = ConnectionSocket.RemoteEndPoint.ToString(); richTextBox2.Text += "成功與客戶端" + remotePoint + "建立連線\r\n"; richTextBox3.Text += DateTime.Now+":"+remotePoint + "\r\n"; ClientInformation.Add(remotePoint, ConnectionSocket); Thread thread = new Thread(ReceiveMessage); thread.IsBackground = true; thread.Start(ConnectionSocket); } } private void ReceiveMessage(Object SocketClient) { Socket ReceiveSocket = (Socket)SocketClient; while (true) { byte[] result = new byte[1024 * 1024]; try { IPAddress ClientIP = (ReceiveSocket.RemoteEndPoint as IPEndPoint).Address; int ClientPort = (ReceiveSocket.RemoteEndPoint as IPEndPoint).Port; int ReceiveLength = ReceiveSocket.Receive(result); string str = ReceiveSocket.RemoteEndPoint.ToString(); string ReceiveMessage = Encoding.UTF8.GetString(result, 0, ReceiveLength); richTextBox1.Text+= "接收客戶端:" + ReceiveSocket.RemoteEndPoint.ToString() + "時間:" + DateTime.Now.ToString() + "\r\n" + "訊息:" + ReceiveMessage + "\r\n"; if (ClientInformation.Count == 1) continue;//只有一個客戶端 List<string> test = new List<string>(ClientInformation.Keys); for (int i = 0; i < ClientInformation.Count; i++) { Socket socket = ClientInformation[test[i]]; string s = ReceiveSocket.RemoteEndPoint.ToString(); if (test[i] != s) { richTextBox1.Text += DateTime.Now + "\r\n" + "客戶端" + str + "向客戶端" + test[i] + "傳送訊息:" + ReceiveMessage; string ReceiveMessage1 = DateTime.Now + "\r\n" + "客戶端" + str + "向您傳送訊息:" + ReceiveMessage; socket.Send(Encoding.UTF8.GetBytes(ReceiveMessage1)); } } } catch (Exception ex) { richTextBox2.Text += "監聽出現異常!\r\n"; richTextBox2.Text += "客戶端" + ReceiveSocket.RemoteEndPoint + "已經連線中斷" + "\r\n" + ex.Message + "\r\n" + ex.StackTrace + "\r\n"; string s = ReceiveSocket.RemoteEndPoint.ToString(); ClientInformation.Remove(s); ReceiveSocket.Shutdown(SocketShutdown.Both); ReceiveSocket.Close(); break; } } } } }介面效果:
注:我這裡在線列表顯示的是所有連線過伺服器的客戶端,對於可能出現的亂碼問題,將相應的ASCII改為UTF-8即可
新手我建議可以先看這兩位博主的文章:
https://www.cnblogs.com/vaevvaev/p/6865968.html
https://www.cnblogs.com/yy3b2007com/p/7476458.html
客戶端:
伺服器: