C# Winform 服务器和多个客户端通讯

实现功能效果如图所示:
C# Winform 服务器和多个客户端通讯
文章图片


1、服务器端:
【C# Winform 服务器和多个客户端通讯】 服务器界面如下:
C# Winform 服务器和多个客户端通讯
文章图片

代码如下:

public partial class Form1 : Form { public Form1() { InitializeComponent(); //关闭对文本框的非线程操作检查 TextBox.CheckForIllegalCrossThreadCalls = false; }string RemoteEndPoint; //客户端的网络结点Thread threadwatch = null; //负责监听客户端的线程 Socket socketwatch = null; //负责监听客户端的套接字 //创建一个和客户端通信的套接字 Dictionary dic = new Dictionary { }; //定义一个集合,存储客户端信息private void btnServerListen_Click(object sender, EventArgs e) { btnServerListen.Enabled = false; //定义一个套接字用于监听客户端发来的消息,包含三个参数(IP4寻址协议,流式连接,Tcp协议) socketwatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //服务端发送信息需要一个IP地址和端口号 IPAddress address = IPAddress.Parse(txtServerIP.Text.Trim()); //获取文本框输入的IP地址//将IP地址和端口号绑定到网络节点point上 IPEndPoint point = new IPEndPoint(address, int.Parse(txtServerPort.Text.Trim())); //获取文本框上输入的端口号 //此端口专门用来监听的//监听绑定的网络节点 socketwatch.Bind(point); //将套接字的监听队列长度限制为20 socketwatch.Listen(20); //创建一个监听线程 threadwatch = new Thread(watchconnecting); //将窗体线程设置为与后台同步,随着主线程结束而结束 threadwatch.IsBackground = true; //启动线程 threadwatch.Start(); //启动线程后 textBox3文本框显示相应提示 txtRecv.AppendText("开始监听客户端传来的信息!" + "\r\n"); }void OnlineList_Disp(string Info) { txtClientIP.Items.Add(Info); //在线列表中显示连接的客户端套接字 }//监听客户端发来的请求 private void watchconnecting() { Socket connection = null; while (true)//持续不断监听客户端发来的请求 { try { connection = socketwatch.Accept(); } catch (Exception ex) { txtRecv.AppendText(ex.Message); //提示套接字监听异常 break; } //获取客户端的IP和端口号 IPAddress clientIP = (connection.RemoteEndPoint as IPEndPoint).Address; int clientPort = (connection.RemoteEndPoint as IPEndPoint).Port; //让客户显示"连接成功的"的信息 string sendmsg = "连接服务端成功!\r\n" + "本地IP:" + clientIP + ",本地端口" + clientPort.ToString(); byte[] arrSendMsg = Encoding.UTF8.GetBytes(sendmsg); connection.Send(arrSendMsg); RemoteEndPoint = connection.RemoteEndPoint.ToString(); //客户端网络结点号 txtRecv.AppendText("成功与" + RemoteEndPoint + "客户端建立连接!\t\n"); //显示与客户端连接情况 dic.Add(RemoteEndPoint, connection); //添加客户端信息OnlineList_Disp(RemoteEndPoint); //显示在线客户端//IPEndPoint netpoint = new IPEndPoint(clientIP,clientPort); IPEndPoint netpoint = connection.RemoteEndPoint as IPEndPoint; //创建一个通信线程 ParameterizedThreadStart pts = new ParameterizedThreadStart(recv); Thread thread = new Thread(pts); thread.IsBackground = true; //设置为后台线程,随着主线程退出而退出 //启动线程 thread.Start(connection); } }/// /// 接收客户端发来的信息 /// ///客户端套接字对象 private void recv(object socketclientpara) {Socket socketServer = socketclientpara as Socket; while (true) { //创建一个内存缓冲区 其大小为1024*1024字节即1M byte[] arrServerRecMsg = new byte[1024 * 1024]; //将接收到的信息存入到内存缓冲区,并返回其字节数组的长度 try { int length = socketServer.Receive(arrServerRecMsg); //将机器接受到的字节数组转换为人可以读懂的字符串 string strSRecMsg = Encoding.UTF8.GetString(arrServerRecMsg, 0, length); //将发送的字符串信息附加到文本框txtMsg上 txtRecv.AppendText("客户端:" + socketServer.RemoteEndPoint + ",time:" + GetCurrentTime() + "\r\n" + strSRecMsg + "\r\n\n"); } catch (Exception ex) { txtRecv.AppendText("客户端" + socketServer.RemoteEndPoint + "已经中断连接" + "\r\n"); //提示套接字监听异常 txtClientIP.Items.Remove(socketServer.RemoteEndPoint.ToString()); //从listbox中移除断开连接的客户端 socketServer.Close(); //关闭之前accept出来的和客户端进行通信的套接字 break; } } }/// /// 获取当前系统时间的方法 /// /// private DateTime GetCurrentTime() { DateTime currentTime = new DateTime(); currentTime = DateTime.Now; return currentTime; }private void btnSend_Click(object sender, EventArgs e) { string sendMsg = txtSend.Text.Trim() + "\r\n"; //要发送的信息 //byte[] bytes = System.Text.Encoding.UTF8.GetBytes(sendMsg); //将要发送的信息转化为字节数组,因为Socket发送数据时是以字节的形式发送的 byte[] bytes = System.Text.Encoding.ASCII.GetBytes(sendMsg); //将要发送的信息转化为字节数组,因为Socket发送数据时是以字节的形式发送的 if (txtClientIP.SelectedIndex == -1) { MessageBox.Show("请选择要发送的客户端!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Stop); } else { string selectClient = txtClientIP.Text; //选择要发送的客户端 dic[selectClient].Send(bytes); //发送数据 txtSend.Clear(); //txtRecv.AppendText(label4.Text + GetCurrentTime() + "\r\n" + sendMsg + "\r\n"); }}private void btnSendAll_Click(object sender, EventArgs e) { string sendMsg = txtSend.Text.Trim() + "\r\n"; //要发送的信息 //将要发送的信息转化为字节数组,因为Socket发送数据时是以字节的形式发送的 byte[] bytes = System.Text.Encoding.ASCII.GetBytes(sendMsg); int count = txtClientIP.Items.Count; if(count<1) { MessageBox.Show("当前无客户端连接!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Stop); } foreach(var selectClient in txtClientIP.Items) { string str = selectClient.ToString(); dic[str].Send(bytes); //发送数据 }} }

2、客户端。
界面如下:
C# Winform 服务器和多个客户端通讯
文章图片

代码如下:
public Form1() { InitializeComponent(); //关闭对文本框的非法线程操作检查 TextBox.CheckForIllegalCrossThreadCalls = false; }//创建 1个客户端套接字 和1个负责监听服务端请求的线程 Thread threadclient = null; Socket socketclient = null; List mlist = new List(); private void btnConnect_Click(object sender, EventArgs e) { //SocketException exception; this.btnConnect.Enabled = false; //定义一个套接字监听 socketclient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //获取文本框中的IP地址 IPAddress address = IPAddress.Parse(txtIP.Text.Trim()); //将获取的IP地址和端口号绑定在网络节点上 IPEndPoint point = new IPEndPoint(address, int.Parse(txtPort.Text.Trim())); try { //客户端套接字连接到网络节点上,用的是Connect socketclient.Connect(point); } catch (Exception) { //MessageBox. MessageBox.Show("连接失败\r\n"); this.btnConnect.Enabled = true; return; }threadclient = new Thread(recv); threadclient.IsBackground = true; threadclient.Start(); }// 接收服务端发来信息的方法 private void recv()// { int x = 0; while (true)//持续监听服务端发来的消息 { try { //定义一个1M的内存缓冲区,用于临时性存储接收到的消息 byte[] arrRecvmsg = new byte[1024 * 1024]; //将客户端套接字接收到的数据存入内存缓冲区,并获取长度 int length = socketclient.Receive(arrRecvmsg); //将套接字获取到的字符数组转换为人可以看懂的字符串 string strRevMsg = Encoding.UTF8.GetString(arrRecvmsg, 0, length); if (x == 1) { txtRecv.AppendText("服务器:" + GetCurrentTime() + "\r\n" + strRevMsg + "\r\n\n"); } else {txtRecv.AppendText(strRevMsg + "\r\n\n"); x = 1; } } catch (Exception ex) { //txtRecv.AppendText("远程服务器已经中断连接" + "\r\n"); this.btnConnect.Enabled = true; break; } } }//获取当前系统时间 private DateTime GetCurrentTime() { DateTime currentTime = new DateTime(); currentTime = DateTime.Now; return currentTime; }//发送字符信息到服务端的方法 private void ClientSendMsg(string sendMsg) { //将输入的内容字符串转换为机器可以识别的字节数组 byte[] arrClientSendMsg = Encoding.UTF8.GetBytes(sendMsg); //调用客户端套接字发送字节数组 socketclient.Send(arrClientSendMsg); //将发送的信息追加到聊天内容文本框中 txtRecv.AppendText(this.label4.Text + ": " + GetCurrentTime() + "\r\n" + sendMsg + "\r\n\n"); }private void btnSend_Click(object sender, EventArgs e) { //调用ClientSendMsg方法 将文本框中输入的信息发送给服务端 ClientSendMsg(txtSend.Text.Trim()); //txtSend.Clear(); }private void txtSend_KeyDown(object sender, KeyEventArgs e) { //当光标位于文本框时 如果用户按下了键盘上的Enter键 if (e.KeyCode == Keys.Enter) { //则调用客户端向服务端发送信息的方法 ClientSendMsg(txtSend.Text.Trim()); txtSend.Clear(); } }private void btnExit_Click(object sender, EventArgs e) { Application.Exit(); }private void Form1_FormClosing(object sender, FormClosingEventArgs e) { DialogResult result = MessageBox.Show("是否退出?选否,最小化到托盘", "操作提示", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question); if (result == DialogResult.Yes) { if (threadclient!=null) { threadclient.Abort(); }Thread.Sleep(500); if (socketclient == null) { this.Dispose(); } else { socketclient.Close(); this.Dispose(); } } else if (result == DialogResult.Cancel) { e.Cancel = true; } else { e.Cancel = true; this.WindowState = FormWindowState.Minimized; this.Visible = false; //this.notifyIcon1.Visible = true; this.ShowInTaskbar = false; }}}


    推荐阅读