服務端
1 using System; 2 using System.Collections.Generic; 3 using System.Net; 4 using System.Net.Sockets; 5 using System.Text; 6 using System.Threading; 7 using System.Windows.Forms; 8 9 namespace csharpService 10 { 11 public partial class Service : Form 12 { 13 public Service() 14 { 15 InitializeComponent(); 16 17 ///多線程編程中,如果子線程需要使用主線程中創建的對象和控件,最好在主線程中體現進行檢查取消 18 /// 19 CheckForIllegalCrossThreadCalls = false; 20 21 /// 獲取本地IP 22 textBox_current_address.Text = IPAddress.Any.ToString(); 23 } 24 25 /// 創建一個字典,用來存儲記錄服務器與客戶端之間的連接(線程問題) 26 /// 27 private Dictionary<string, Socket> clientList = new Dictionary<string, Socket>(); 28 29 /// 創建連接 30 private void button_connect_Click(object sender, EventArgs e) 31 { 32 Thread myServer = new Thread(MySocket); 33 //設置這個線程是后台線程 34 myServer.IsBackground = true; 35 myServer.Start(); 36 } 37 38 //①:創建一個用於監聽連接的Socket對象; 39 //②:用指定的端口號和服務器的Ip建立一個EndPoint對象; 40 //③:用Socket對象的Bind()方法綁定EndPoint; 41 //④:用Socket對象的Listen()方法開始監聽; 42 //⑤:接收到客戶端的連接,用Socket對象的Accept()方法創建一個新的用於和客戶端進行通信的Socket對象; 43 //⑥:通信結束后一定記得關閉Socket。 44 45 /// 創建連接的方法 46 private void MySocket() 47 { 48 //1.創建一個用於監聽連接的Socket對象; 49 Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP); 50 51 //2.用指定的端口號和服務器的Ip建立一個EndPoint對象; 52 IPAddress iP = IPAddress.Parse(textBox_current_address.Text); 53 IPEndPoint endPoint = new IPEndPoint(iP, int.Parse(textBox_port.Text)); 54 55 //3.用Socket對象的Bind()方法綁定EndPoint; 56 server.Bind(endPoint); 57 58 //4.用Socket對象的Listen()方法開始監聽; 59 60 //同一時刻內允許同時加入鏈接的最大數量 61 server.Listen(20); 62 listBox_log.Items.Add("服務器已經成功開啟!"); 63 64 //5.接收到客戶端的連接,用Socket對象的Accept()方法創建一個新的用於和客戶端進行通信的Socket對象; 65 while (true) 66 { 67 //接受接入的一個客戶端 68 Socket connectClient = server.Accept(); 69 if (connectClient != null) 70 { 71 string infor = connectClient.RemoteEndPoint.ToString(); 72 clientList.Add(infor, connectClient); 73 74 listBox_log.Items.Add(infor + "加入服務器!"); 75 76 ///服務器將消息發送至客服端 77 string msg = infor + "已成功進入到聊天室!"; 78 79 SendMsg(msg); 80 81 //每有一個客戶端接入時,需要有一個線程進行服務 82 83 Thread threadClient = new Thread(ReciveMsg);//帶參的方法可以把傳遞的參數放到start中 84 threadClient.IsBackground = true; 85 86 //創建的新的對應的Socket和客戶端Socket進行通信 87 threadClient.Start(connectClient); 88 } 89 } 90 } 91 92 /// 服務器接收到客戶端發送的消息 93 private void ReciveMsg(object o) 94 { 95 //Socket connectClient = (Socket)o; //與下面效果一樣 96 97 Socket connectClient = o as Socket;//connectClient負責客戶端的通信 98 IPEndPoint endPoint = null; 99 while (true) 100 { 101 try 102 { 103 ///定義服務器接收的字節大小 104 byte[] arrMsg = new byte[1024 * 1024]; 105 106 ///接收到的信息大小(所占字節數) 107 int length = connectClient.Receive(arrMsg); 108 109 110 111 if (length > 0) 112 { 113 string recMsg = Encoding.UTF8.GetString(arrMsg, 0, length); 114 //獲取客戶端的端口號 115 endPoint = connectClient.RemoteEndPoint as IPEndPoint; 116 //服務器顯示客戶端的端口號和消息 117 listBox_log.Items.Add(DateTime.Now + "[" + endPoint.Port.ToString() + "]:" + recMsg); 118 119 //服務器(connectClient)發送接收到的客戶端信息給客戶端 120 SendMsg("[" + endPoint.Port.ToString() + "]:" + recMsg); 121 } 122 } 123 catch (Exception) 124 { 125 ///移除添加在字典中的服務器和客戶端之間的線程 126 clientList.Remove(endPoint.ToString()); 127 128 connectClient.Dispose(); 129 130 131 132 133 } 134 } 135 } 136 137 /// 服務器發送消息,客戶端接收 138 private void SendMsg(string str) 139 { 140 ///遍歷出字典中的所有線程 141 foreach (var item in clientList) 142 { 143 byte[] arrMsg = Encoding.UTF8.GetBytes(str); 144 145 ///獲取鍵值(服務器),發送消息 146 item.Value.Send(arrMsg); 147 } 148 } 149 } 150 }
客戶端:
1 using System; 2 using System.Net; 3 using System.Net.Sockets; 4 using System.Text; 5 using System.Threading; 6 using System.Windows.Forms; 7 8 namespace csharp_Client 9 { 10 public partial class Client : Form 11 { 12 public Client() 13 { 14 InitializeComponent(); 15 16 ///多線程編程中,如果子線程需要使用主線程中創建的對象和控件,最好在主線程中體現進行檢查取消 17 CheckForIllegalCrossThreadCalls = false; 18 } 19 20 /// 創建客戶端 21 private Socket client; 22 23 private void button_connect_Click(object sender, EventArgs e) 24 { 25 ///創建客戶端 26 client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP); 27 ///IP地址 28 IPAddress ip = IPAddress.Parse(textBox_address.Text); 29 ///端口號 30 IPEndPoint endPoint = new IPEndPoint(ip, int.Parse(textBox_port.Text)); 31 ///建立與服務器的遠程連接 32 try 33 { 34 client.Connect(endPoint); 35 } 36 catch(Exception) 37 { 38 MessageBox.Show("地址或端口錯誤!!!!"); 39 return; 40 } 41 ///線程問題 42 Thread thread = new Thread(ReciveMsg); 43 thread.IsBackground = true; 44 thread.Start(client); 45 } 46 47 /// 客戶端接收到服務器發送的消息 48 private void ReciveMsg(object o) 49 { 50 Socket client = o as Socket; 51 while (true) 52 { 53 try 54 { 55 ///定義客戶端接收到的信息大小 56 byte[] arrList = new byte[1024 * 1024]; 57 ///接收到的信息大小(所占字節數) 58 int length = client.Receive(arrList); 59 string msg = DateTime.Now + Encoding.UTF8.GetString(arrList, 0, length); 60 listBox_log.Items.Add(msg); 61 } 62 catch (Exception) 63 { 64 ///關閉客戶端 65 client.Close(); 66 } 67 } 68 } 69 70 /// 客戶端發送消息給服務端 71 private void button_send_Click(object sender, EventArgs e) 72 { 73 if (textBox_message.Text != "") 74 { 75 SendMsg(textBox_message.Text); 76 } 77 } 78 79 /// 客戶端發送消息,服務端接收 80 private void SendMsg(string str) 81 { 82 byte[] arrMsg = Encoding.UTF8.GetBytes(str); 83 client.Send(arrMsg); 84 } 85 86 87 private void Client_FormClosed(object sender, FormClosedEventArgs e) 88 { 89 if(client!=null) client.Close(); 90 } 91 } 92 }