服务端
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 }