用Socket编写的聊天小程序

Socket是什么?

是套接字,除此之外我也不太清楚,先略过

 

直接上实例,首先服务端:

复制代码
 private int ServerPoint = 8102;  //自定义端口号
 private string ServerUser = "Tracy"; //自定义昵称
 private Socket clientSK;
 private delegate void AppendRich(string txt,string user); //定义委托是为了避免在AppendText时出现"richTextBox1不是该线程创建"的错误提示

 private void Form1_Load(object sender, EventArgs e)
 {
            Thread listenThread = new Thread(new ThreadStart(AppInit));
            listenThread.Start(); //用多线程是为了防止sk.Listen(10)一直处于监听状态,导致UI界面卡死
 }
 private void AppInit()
 {
            Socket sk = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            EndPoint endPoint = new IPEndPoint(IPAddress.Any, ServerPoint);
            sk.Bind(endPoint); //实例化Socket并绑定端口
            sk.Listen(10); //开始监听,如果没有客户端连接将一直卡在这

            clientSK = sk.Accept(); //客户端连接,把这个有效的Socket连接赋给全局变量clientSK,程序继续走
            SendMsg("已成功连接到服务器", "系统消息");

            AppendRich dele = new AppendRich(AppendToRich); //实例化一个委托

            while (true) //用死循环保持一直通话
            {
                try
                {
                    byte[] receiveBT = new byte[1024];
                    int receiveInt = clientSK.Receive(receiveBT); //获取接收的消息
                    if (receiveInt == 0) //如果接收到空消息,跳出循环
                    {
                        break;
                    }
                    string receiveStr = Encoding.UTF8.GetString(receiveBT, 0, receiveInt); //接收的消息转为string
                    richTextBox1.Invoke(dele, new object[] { receiveStr.Substring(9), receiveStr.Substring(0, 9).Trim() }); //添加到richbox中,这里我自定义了string的格式,分昵称和消息内容
                }
                catch (Exception ex)
                {
                    break;
                }
            }
            //此时跳出了循环,意味着程序即将关闭
            clientSK.Close();  //关闭连接到客户端的Socket
            sk.Close();  //关闭实例化的Socket
            richTextBox1.Invoke(dele, new object[] { "连接已终止", "系统消息" }); //利用委托向RichTextBox1中添加String
 }
 private void SendMsg(string txt, string user)
 {
            string nickName = user;
            string sendStr = nickName.PadLeft(9) + txt;
            byte[] bs = Encoding.UTF8.GetBytes(sendStr);
            clientSK.Send(bs, bs.Length, 0);//向客户端发送信息
 }
 private void AppendToRich(string txt,string user)
 {
            if (txt == string.Empty)
            {
                return;
            }
            if (user == ServerUser)  //判断用户,以便区分颜色和字体
            {
                richTextBox1.SelectionFont = new Font(new FontFamily("宋体"), 9);
                richTextBox1.SelectionColor = Color.Green;
            }
            else
            {
                richTextBox1.SelectionFont = new Font(new FontFamily("宋体"), 9);
                richTextBox1.SelectionColor = Color.Blue;
            }
            richTextBox1.AppendText("\r\n" + user + " " + DateTime.Now.ToString("HH:mm:ss") + "\r\n");

            if (user == ServerUser)
            {
                richTextBox1.SelectionFont = new Font(new FontFamily("楷体"), 12);
                richTextBox1.SelectionColor = Color.FromArgb(0, 155, 255);
            }
            else
            {
                richTextBox1.SelectionFont = new Font(new FontFamily("宋体"), 9);
                richTextBox1.SelectionColor = Color.Black;
            }
            richTextBox1.AppendText(txt);
            richTextBox1.ScrollToCaret();//滚动条保持最底部
            textBox2.ResetText();
            textBox2.Focus();
 }
ServerCode
复制代码

 

 

 

 

客户端:

复制代码
 private int ServerPoint = 8102;  //自定义端口号,要与之前服务端一致
 private string ClientUser = "诺克萨斯", ClientIP = "127.0.0.1"; //自定义昵称,以及服务端IP
 private Socket newclient;
 private delegate void AppendRich(string txt, string user);

 private void Form1_Load(object sender, EventArgs e)
 {
            Thread listenThread = new Thread(new ThreadStart(AppInit));
            listenThread.Start();
 }

 private void AppInit()
 {

            newclient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint ie = new IPEndPoint(IPAddress.Parse(ClientIP), ServerPoint); // 服务器的IP和端口
            newclient.Connect(ie); //这里不需要绑定,直接连接到服务端
            string hostName= Dns.GetHostName(); //获取客户端主机名
            IPHostEntry iphostentry = Dns.GetHostEntry(hostName);
            List<IPAddress> ips=iphostentry.AddressList.ToList(); //获取客户端IP

            SendMsg(ips[2].ToString() + " 已连接", "系统消息");
            AppendRich dele = new AppendRich(AppendToRich);

            while (true)
            {
                try
                {
                    byte[] receiveBT = new byte[1024];
                    int receiveInt = newclient.Receive(receiveBT); //获取接收的消息
                    if (receiveInt == 0)
                    {
                        break;
                    }
                    string receiveStr = Encoding.UTF8.GetString(receiveBT, 0, receiveInt); //接收的消息转为string
                    richTextBox1.Invoke(dele, new object[] { receiveStr.Substring(9), receiveStr.Substring(0, 9).Trim() }); //添加到richbox中
                }
                catch(Exception ex)
                {
                    break;
                }
            }
            newclient.Close();
            richTextBox1.Invoke(dele, new object[] { "连接已终止", "系统消息" });
 }
 private void SendMsg(string txt, string user)
 {
            string nickName = user;
            string sendStr = nickName.PadLeft(9) + txt;
            byte[] bs = Encoding.UTF8.GetBytes(sendStr);
            newclient.Send(bs, bs.Length, 0);//发送信息
 }
 private void AppendToRich(string txt, string user)
 {
            if (txt == string.Empty)
            {
                return;
            }
            richTextBox1.AppendText("\r\n" + user + " " + DateTime.Now.ToString("HH:mm:ss") + "\r\n" + txt);
            richTextBox1.ScrollToCaret();//滚动条保持最底部
            textBox1.ResetText();
            textBox1.Focus();
 }
ClientCode
复制代码

 

posted on   邓绍俊  阅读(319)  评论(0编辑  收藏  举报

编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示