C#开发简单的聊天程序
最近在b站看到一个用C#&Socket实现一个简易聊天程序的视频,感觉挺不错的就照着学习了一下,顺便做个笔记。
socket通信原理图:
服务端(WinForm):
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace SocketServer { public partial class MainForm : Form { public List<Socket> clientList = new List<Socket>(); public MainForm() { InitializeComponent(); } private void startBtn_Click(object sender, EventArgs e) { //1、创建socket对象 Socket socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp); //2、绑定ip和端口 socket.Bind(new IPEndPoint(IPAddress.Parse(ipContent.Text),int.Parse(portContent.Text))); //3、开启监听 socket.Listen(10); //4、开始接收客户端消息 ThreadPool.QueueUserWorkItem(new WaitCallback(acceptClient),socket); this.AppendTxtToShowLog(string.Format("服务器启动成功!")) ; } private void acceptClient(object server) { Socket socket = server as Socket; while (true) { Socket clientSocket=socket.Accept();//接收客户端连接 clientList.Add(clientSocket); this.AppendTxtToShowLog(string.Format("客户端{0}连接成功", clientSocket.RemoteEndPoint.ToString())); //不断接收客户端发来的消息 ThreadPool.QueueUserWorkItem(new WaitCallback(receiveClient),clientSocket); } } private void receiveClient(object client) { Socket clientSocket = client as Socket; byte[] data = new byte[1024 * 1024]; while (true) { int len = 0; try { len = clientSocket.Receive(data, 0, data.Length, SocketFlags.None);//接收字节数组,并获取长度 } catch (Exception)//客户端异常退出 { try { this.AppendTxtToShowLog(string.Format("客户端{0}异常退出", clientSocket.RemoteEndPoint.ToString())); } catch (Exception) { } clientList.Remove(clientSocket); stopConnect(clientSocket);//关闭连接 return; } if (len <= 0)//客户端正常退出 { try { this.AppendTxtToShowLog(string.Format("客户端{0}正常退出", clientSocket.RemoteEndPoint.ToString())); } catch (Exception) { } clientList.Remove(clientSocket); stopConnect(clientSocket);//关闭连接 return; } string str=Encoding.Default.GetString(data,0,len);//将字节数组转换成字符串 this.AppendTxtToShowLog(string.Format("客户端{0}发来信息:{1}",clientSocket.RemoteEndPoint.ToString(),str)); } } //关闭连接 private void stopConnect(Socket clientSocket) { if (clientSocket.Connected) { try { clientSocket.Shutdown(SocketShutdown.Both); clientSocket.Close(100); } catch (Exception) { } } } private void AppendTxtToShowLog(string str)//添加日志记录 { if (showLog.InvokeRequired) { showLog.BeginInvoke(new Action<string>(s => { showLog.Text = string.Format("{0}\r\n{1}", s, this.showLog.Text); }), str); } else { showLog.Text = string.Format("{0}\r\n{1}", str, this.showLog.Text); } } private void sendBtn_Click(object sender, EventArgs e) { foreach (var clientSocket in clientList) { if (clientSocket.Connected) { byte[] data = Encoding.Default.GetBytes(this.sendContent.Text); clientSocket.Send(data,0,data.Length,SocketFlags.None); } } } private void MainForm_FormClosing(object sender, FormClosingEventArgs e) { foreach (var clientSocket in clientList) { if (clientSocket.Connected) { try { clientSocket.Shutdown(SocketShutdown.Both); clientSocket.Close(); } catch (Exception) { } } } } } }
客户端(WinForm):
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace SocketClient { public partial class MainForm : Form { public Socket clientSocket { get; set; } public MainForm() { InitializeComponent(); } private void connectBtn_Click(object sender, EventArgs e) { //1、创建socket Socket socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp); clientSocket = socket; //2、连接服务器(ip+port) try { socket.Connect(IPAddress.Parse(ipContent.Text), int.Parse(portContent.Text)); } catch (Exception ex) { //Thread.Sleep(10); //connectBtn_Click(this,e); MessageBox.Show("连接失败"); return; } //3、开始接收信息 Thread thread = new Thread(new ParameterizedThreadStart(receiveData)); thread.IsBackground = true; thread.Start(clientSocket); } private void receiveData(object socket) { byte[] data = new byte[1024 * 1024]; while (true) { int len = 0; try { len = clientSocket.Receive(data, 0, data.Length - 1, SocketFlags.None); } catch (Exception) { try { this.AppendTxtToShowLog(string.Format("服务端{0}异常退出", clientSocket.RemoteEndPoint.ToString())); } catch (Exception) { } stopConnect();//关闭连接 return; } if (len <= 0) { try { this.AppendTxtToShowLog(string.Format("服务端{0}正常退出", clientSocket.RemoteEndPoint.ToString())); } catch (Exception) { } stopConnect();//关闭连接 return; } string str = Encoding.Default.GetString(data,0,len); AppendTxtToShowLog(string.Format("服务端发来信息:{0}",str)); } } //关闭连接 private void stopConnect() { if (clientSocket.Connected) { try { clientSocket.Shutdown(SocketShutdown.Both); clientSocket.Close(100); } catch (Exception) { } } } private void AppendTxtToShowLog(string str)//添加日志记录 { if (showLog.InvokeRequired) { showLog.BeginInvoke(new Action<string>(s => { showLog.Text = string.Format("{0}\r\n{1}", s, this.showLog.Text); }), str); } else { showLog.Text = string.Format("{0}\r\n{1}", str, this.showLog.Text); } } private void sendBtn_Click(object sender, EventArgs e) { if (clientSocket.Connected) { byte[] data = Encoding.Default.GetBytes(sendContent.Text); clientSocket.Send(data, 0, data.Length, SocketFlags.None); } } private void MainForm_FormClosing(object sender, FormClosingEventArgs e) { //判断是否连接,如果连接则关闭连接 stopConnect(); } } }
效果图:
评论