C# winform socket一个服务端和多个客户端进行通信

转载地址:http://blog.youkuaiyun.com/zdyueguanyun/article/details/51208227


参看此链接http://blog.youkuaiyun.com/zdyueguanyun/article/details/51207727

在上述代码的基础上进行了修改,包括一些捕获异常以及按钮的应用,扩充了一个listbox确保服务端可以选择和不同的客户端进行通信

代码:

using System;  
using System.Collections.Generic;  
using System.ComponentModel;  
using System.Data;  
using System.Drawing;  
using System.Linq;  
using System.Text;  
using System.Windows.Forms;  
using System.Threading;  
using System.Net.Sockets;  
using System.Net;  
using System.Collections;  
namespace chat1  
{  
      
      
    public partial class Form1 : Form  
    {  
        public Form1()  
        {  
            InitializeComponent();  
            StartPosition = FormStartPosition.CenterScreen;  
  
            //关闭对文本框的非线程操作检查  
            TextBox.CheckForIllegalCrossThreadCalls = false;  
        }  
        string RemoteEndPoint;     //客户端的网络结点  
  
        Thread threadwatch = null;//负责监听客户端的线程  
        Socket socketwatch = null;//负责监听客户端的套接字  
        //创建一个和客户端通信的套接字  
        Dictionary<string, Socket> dic = new Dictionary<string, Socket> { };   //定义一个集合,存储客户端信息  
  
          
  
  
        private void button1_Click(object sender, EventArgs e)  
        {  
            this.button1.Enabled = false;  
            //定义一个套接字用于监听客户端发来的消息,包含三个参数(IP4寻址协议,流式连接,Tcp协议)  
            socketwatch = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);  
  
            //服务端发送信息需要一个IP地址和端口号  
            IPAddress address = IPAddress.Parse(textBox1.Text.Trim());//获取文本框输入的IP地址  
  
            //将IP地址和端口号绑定到网络节点point上  
            IPEndPoint point = new IPEndPoint(address,int.Parse(textBox2.Text.Trim()));//获取文本框上输入的端口号  
            //此端口专门用来监听的  
  
            //监听绑定的网络节点  
            socketwatch.Bind(point);  
  
            //将套接字的监听队列长度限制为20  
            socketwatch.Listen(20);  
  
              
  
            //创建一个监听线程  
            threadwatch = new Thread(watchconnecting);     
  
  
             
            //将窗体线程设置为与后台同步,随着主线程结束而结束  
            threadwatch.IsBackground = true;    
   
           //启动线程     
            threadwatch.Start();   
    
           //启动线程后 textBox3文本框显示相应提示  
           textBox3.AppendText("开始监听客户端传来的信息!" + "\r\n");  
            
  
  
        }  
  
        void OnlineList_Disp(string Info)  
        {  
            listBoxOnlineList.Items.Add(Info);   //在线列表中显示连接的客户端套接字  
        }  
  
  
          
        //监听客户端发来的请求  
        private void watchconnecting()  
        {  
            Socket connection = null;  
            while (true)  //持续不断监听客户端发来的请求     
            {  
                try    
                {     
                    connection = socketwatch.Accept();    
                }     
                catch (Exception ex)     
                {    
                    textBox3.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(); //客户端网络结点号  
                textBox3.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上     
                    textBox3.AppendText("客户端:" + socketServer.RemoteEndPoint+",time:" + GetCurrentTime() + "\r\n" + strSRecMsg + "\r\n\n");  
                }  
                catch (Exception ex)  
                {  
                    textBox3.AppendText("客户端"+socketServer.RemoteEndPoint+"已经中断连接"+"\r\n"); //提示套接字监听异常   
                    listBoxOnlineList.Items.Remove(socketServer.RemoteEndPoint.ToString());//从listbox中移除断开连接的客户端  
                    socketServer.Close();//关闭之前accept出来的和客户端进行通信的套接字  
                    break;     
                }  
            }     
  
          
        }  
  
  
        ///      
        /// 获取当前系统时间的方法     
        ///      
        /// 当前时间     
        private DateTime GetCurrentTime()     
        {     
            DateTime currentTime = new DateTime();     
            currentTime = DateTime.Now;     
            return currentTime;     
        }  
  
  
        //发送信息到客户端   
        private void button2_Click(object sender, EventArgs e)  
        {  
            string sendMsg = textBox4.Text.Trim();  //要发送的信息  
            byte[] bytes = System.Text.Encoding.UTF8.GetBytes(sendMsg);   //将要发送的信息转化为字节数组,因为Socket发送数据时是以字节的形式发送的  
  
            if (listBoxOnlineList.SelectedIndex == -1)  
            {  
                MessageBox.Show("请选择要发送的客户端!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Stop);  
            }  
            else  
            {  
                string selectClient = listBoxOnlineList.Text;  //选择要发送的客户端  
                dic[selectClient].Send(bytes);   //发送数据  
                textBox4.Clear();  
                textBox3.AppendText(label4.Text + GetCurrentTime() + "\r\n" + sendMsg + "\r\n");     
  
            }  
  
          
             
        }  
  
         
        
  
        //快捷键 Enter 发送信息   
       private void textBox4_KeyDown(object sender, KeyEventArgs e)  
        {  
            //如果用户按下了Enter键     
            if (e.KeyCode == Keys.Enter)  
            {  
                string sendMsg = textBox4.Text.Trim();  //要发送的信息  
                byte[] bytes = System.Text.Encoding.UTF8.GetBytes(sendMsg);   
                if (listBoxOnlineList.SelectedIndex == -1)  
                {  
                    MessageBox.Show("请选择要发送的客户端!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Stop);  
                }  
                else  
                {  
  
                    string selectClient = listBoxOnlineList.Text;  //选择要发送的客户端  
                    dic[selectClient].Send(bytes);   //发送数据  
                    textBox4.Clear();  
                    textBox3.AppendText(label4.Text + GetCurrentTime() + "\r\n" + sendMsg + "\r\n");  
  
                }  
            }  
        }  
  
  
        private void Form1_Load(object sender, EventArgs e)  
        {  
  
        }  
  
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)  
        {  
            DialogResult result = MessageBox.Show("是否退出?选否,最小化到托盘", "操作提示", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);  
            if (result == DialogResult.Yes)  
            {  
                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;  
            }  
        }  
  
        private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)  
        {  
            base.Visible = true;  
            this.notifyIcon1.Visible = false;  
            this.ShowInTaskbar = true;  
            //base.Show();  
            base.WindowState = FormWindowState.Normal;  
        }   
    }  
}  

客户端代码:

using System;  
using System.Collections.Generic;  
using System.ComponentModel;  
using System.Data;  
using System.Drawing;  
using System.Linq;  
using System.Text;  
using System.Windows.Forms;  
using System.Threading;  
using System.Net.Sockets;  
using System.Net;  
  
  
namespace chat2  
{  
    public partial class Form1 : Form  
    {  
        public Form1()  
        {  
            InitializeComponent();  
            StartPosition = FormStartPosition.CenterScreen;  
            //关闭对文本框的非法线程操作检查  
            TextBox.CheckForIllegalCrossThreadCalls = false;  
        }  
  
        //创建 1个客户端套接字 和1个负责监听服务端请求的线程  
        Thread threadclient = null;  
        Socket socketclient = null;  
        List<IPEndPoint> mlist =new List<IPEndPoint>();  
        private void button1_Click(object sender, EventArgs e)  
        {  
            //SocketException exception;  
            this.button1.Enabled = false;  
            //定义一个套接字监听  
            socketclient = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);  
  
            //获取文本框中的IP地址  
            IPAddress address = IPAddress.Parse(textBox1.Text.Trim());  
  
            //将获取的IP地址和端口号绑定在网络节点上  
            IPEndPoint point = new IPEndPoint(address,int.Parse(textBox2.Text.Trim()));  
  
            try  
            {  
                //客户端套接字连接到网络节点上,用的是Connect  
                socketclient.Connect(point);  
            }  
            catch (Exception )  
            {  
                //MessageBox.  
                MessageBox.Show("连接失败\r\n");  
                this.button1.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)  
                    {  
                        textBox3.AppendText("服务器:" + GetCurrentTime() + "\r\n" + strRevMsg + "\r\n\n");  
  
                    }  
                    else  
                    {  
  
                        textBox3.AppendText(strRevMsg + "\r\n\n");  
                        x = 1;  
                    }  
                }  
                catch(Exception ex)  
                {  
                    textBox3.AppendText("远程服务器已经中断连接"+"\r\n");  
                    this.button1.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);     
            //将发送的信息追加到聊天内容文本框中     
            textBox3.AppendText(this.label4.Text+": " + GetCurrentTime() + "\r\n" + sendMsg + "\r\n\n");   
        }  
  
  
  
        //点击按钮button2 向服务端发送信息   
        private void button2_Click(object sender, EventArgs e)  
        {  
            //调用ClientSendMsg方法 将文本框中输入的信息发送给服务端     
            ClientSendMsg(textBox4.Text.Trim());  
            textBox4.Clear();  
        }  
  
          
         
        private void textBox4_KeyDown_1(object sender, KeyEventArgs e)  
        {  
            //当光标位于文本框时 如果用户按下了键盘上的Enter键  
            if (e.KeyCode == Keys.Enter)  
            {  
                //则调用客户端向服务端发送信息的方法    
                ClientSendMsg(textBox4.Text.Trim());  
                textBox4.Clear();  
  
            }  
        }  
  
        private void Form1_Load(object sender, EventArgs e)  
        {  
  
        }  
  
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)  
        {  
            DialogResult result = MessageBox.Show("是否退出?选否,最小化到托盘", "操作提示", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);  
            if (result == DialogResult.Yes)  
            {  
                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;  
            }  
        }  
  
  
  
        private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)  
        {  
            base.Visible = true;  
            this.notifyIcon1.Visible = false;  
            this.ShowInTaskbar = true;  
            //base.Show();  
            base.WindowState = FormWindowState.Normal;  
        }  
    }  
}  

程序还有不足,后期还会继续改进

客户端在断开连接后,应该把socket关闭;

if (result == DialogResult.Yes)

 {
           if (socketclient == null)
            {
                    this.Dispose();
            }
            else
            {
                socketclient.Close();
                this.Dispose();
             }

                      }

其他错误,欢迎大家指出,需要完善的地方,也希望大家给出建议




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值