c#多人聊天室
发布日期:2021-05-07 00:06:32 浏览次数:24 分类:精选文章

本文共 7236 字,大约阅读时间需要 24 分钟。

用c#写的一个多人聊天室的小程序 用的是socket  没用TcpClien以下是代码

客户端:

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.Net;using System.Threading;using System.Net.Sockets;namespace 客户端{    public partial class Form1 : Form    {        Socket lian;        public Form1()        {             InitializeComponent();        }        ///         /// 不停接收信息的线程        ///         void jieshou()        {            while (true)            {                Byte[] buff = new Byte[1000];                try                {                    int s = lian.Receive(buff);                    if (s == 0)                        break;                    string str = Encoding.UTF8.GetString(buff, 0, s);                    this.Invoke(new Action(() =>                    {                        this.neirong.AppendText(str + "\r\n");                    }));                }                catch { }            }        }        ///         /// 发送消息        ///         ///         ///         private void button1_Click(object sender, EventArgs e)        {            if (this.button2.Text != "关闭")            {                MessageBox.Show("请先连接");                return;            }            string str = this.liaotian.Text;            string strr = this.name.Text + ":" + str;            byte[] buf = Encoding.UTF8.GetBytes(strr);            try            {                lian.Send(buf);            }            catch            {                //服务器关闭 或者发生异常 断开连接                lian.Close();                MessageBox.Show("请重新连接");                this.button2.Text = "连接";                return;            }            this.liaotian.Clear();            this.neirong.AppendText("我:" + str + "\r\n");        }        ///         /// 点第一次连接  第二次关闭连接         ///         ///         ///         private void button2_Click(object sender, EventArgs e)        {            if (this.button2.Text == "关闭")            {                lian.Close();                this.button2.Text = "连接";                return;            }            try            {                //创建负责通信的Socket                lian = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);                IPAddress ip = IPAddress.Parse("127.0.0.1");                IPEndPoint point = new IPEndPoint(ip, 3333);                //获得要连接的远程服务器应用程序的IP地址和端口号                lian.Connect(point);                //开启一个新的线程不停的接收服务端发来的消息                Thread t = new Thread(jieshou);                t.IsBackground = true;                t.Start();                this.button2.Text = "关闭";            }            catch            {             }        }    }}
服务器端:

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.Net.Sockets;using System.Net;using System.Threading;namespace 聊天室{    public partial class Form1 : Form    {        //所有通信的socket        List
alllian = new List
(); ///
/// 初始化界面 同时开启服务器监听 /// public Form1() { InitializeComponent(); //防止线程无法访问ui界面的控件 但是隐患太大 推荐使用this.Invoke(new Action(() => //Control.CheckForIllegalCrossThreadCalls = false; try { //新建套接字 Socket jianting = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // 绑定 可用ip jianting.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 3333)); //同时连接的最大上限 多了排队 jianting.Listen(2); //创建后台线程一直等待连接连接 Thread t = new Thread(lianjie); t.IsBackground = true; t.Start(jianting); } catch { } } ///
/// 一直监听 线程只能传object /// ///
void lianjie(object jianting) { while (true) { Socket jt = (Socket)jianting; //返回通信的套接字 try { Socket l = jt.Accept(); //持续接收消息 alllian.Add(l); Thread t = new Thread(jieshou); t.IsBackground = true; t.Start(l); } catch { } } } ///
/// 持续接收发来的消息 /// ///
void jieshou(object ll) { Socket l = (Socket)ll; while (true) { Byte[] buff = new Byte[1000]; try { int s = l.Receive(buff); if (s == 0) { alllian.Remove(l); break; } //显示内容 string str = Encoding.UTF8.GetString(buff, 0, s); this.Invoke(new Action(() => { this.neirong.AppendText(str + "\r\n"); })); buff = Encoding.UTF8.GetBytes(str); //发送给别人 直接用发来bytes转发的话有一些问题 长度不匹配 foreach (Socket all in alllian) { if (all != l) try { all.Send(buff); } catch { continue; } } } catch { } } } ///
/// 发送消息给所有人 /// ///
///
private void fasong_Click(object sender, EventArgs e) { bool r=false; string str = this.liaotian.Text; string strr = "房主:" + str; byte[] buf = Encoding.UTF8.GetBytes(strr); //给所有人发送消息 不要用foreach 报错 集合已修改 无法进行枚举操作 for (int i = 0; i < alllian.Count;i++ ) { try { alllian[i].Send(buf); r = true; } catch { alllian.Remove(alllian[i]); i--; continue; } } //如果可以发送出去消息 则还有人连接 if (r) { this.liaotian.Clear(); this.neirong.AppendText("我:"+str + "\r\n"); } else { alllian.Clear(); MessageBox.Show("无人聊天"); } } }}
写完这个小程序有几点需要总结的:

1.socket、线程、集合的使用  

socket:多练练就会用了 网上资料不少

线程:传参数只能是object 之后可强转 可 as(比较安全)  winform程序线程想访问控件最好使用

this.Invoke(new Action(() => 这类的操作        

而 Control.CheckForIllegalCrossThreadCalls = false; 只是拆了东墙补

集合:在循环里进行操作勿用foreach  比如集合在删除中间元素的时候后面的元素会往前移动 for删除完元素之后 i--退一位即可 

2.通信的双方不能明确的知晓对方是否断开连接

服务器:客户端断开连接,服务器发送消息的时候会报异常

客户端:服务器关闭 ,客户端发送消息会报异常

捕捉这个异常 则证明对方断开连接  做相应的处理(这样不太正规,万一不是断开连接引起的异常就不好了) 这个我用着还可以

3.关于检测对方是否断开连接的方法

百度有不少  心跳包是主流  我的方法是偏方 - - 

上一篇:c#正则表达式 ipv4地址
下一篇:浅谈c#Management的使用

发表评论

最新留言

不错!
[***.144.177.141]2025年03月27日 04时53分42秒