服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - c#基于WinForm的Socket实现简单的聊天室 IM

c#基于WinForm的Socket实现简单的聊天室 IM

2022-11-16 15:17天天向上518 C#

这篇文章主要介绍了c#基于WinForm的Socket实现简单的聊天室 IM的步骤,帮助大家更好的理解和学习使用c#,感兴趣的朋友可以了解下

1:什么是Socket

所谓套接字(Socket),就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。

一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。

从所处的地位来讲,套接字上联应用进程,下联网络协议栈,是应用程序通过网络协议进行通信的接口,是应用程序与网络协议根进行交互的接口。

2:客服端和服务端的通信简单流程

c#基于WinForm的Socket实现简单的聊天室 IM

3:服务端Code:

?
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
 
namespace ChartService
{
    using System.Net;
    using System.Net.Sockets;
    using System.Threading;
    using ChatCommoms;
    using ChatModels;
 
    public partial class ServiceForm : Form
    {
        Socket _socket;
        private static List<ChatUserInfo> userinfo = new List<ChatUserInfo>();
        public ServiceForm()
        {
            InitializeComponent();
 
        }
 
        private void btnServicStart_Click(object sender, EventArgs e)
        {
            try
            {
                string ip = textBox_ip.Text.Trim();
                string port = textBox_port.Text.Trim();
                if (string.IsNullOrWhiteSpace(ip) || string.IsNullOrWhiteSpace(port))
                {
                    MessageBox.Show("IP与端口不可以为空!");
                }
                ServiceStartAccept(ip, int.Parse(port));
            }
            catch (Exception)
            {
                MessageBox.Show("连接失败!或者ip,端口参数异常");
            }
        }
        public void ServiceStartAccept(string ip, int port)
        {
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint endport = new IPEndPoint(IPAddress.Parse(ip), port);
            socket.Bind(endport);
            socket.Listen(10);
            Thread thread = new Thread(Recevice);
            thread.IsBackground = true;
            thread.Start(socket);
            textboMsg.AppendText("服务开启ok...");
        }
 
        /// <summary>
        /// 开启接听服务
        /// </summary>
        /// <param name="obj"></param>
        private void Recevice(object obj)
        {
            var socket = obj as Socket;
            while (true)
            {
                string remoteEpInfo = string.Empty;
                try
                {
                    Socket txSocket = socket.Accept();
                    _socket = txSocket;
                    if (txSocket.Connected)
                    {
                        remoteEpInfo = txSocket.RemoteEndPoint.ToString();
                        textboMsg.AppendText($"\r\n{remoteEpInfo}:连接上线了...");
                        var clientUser = new ChatUserInfo
                        {
                            UserID = Guid.NewGuid().ToString(),
                            ChatUid = remoteEpInfo,
                            ChatSocket = txSocket
                        };
                        userinfo.Add(clientUser);
 
 
                        listBoxCoustomerList.Items.Add(new ChatUserInfoBase { UserID = clientUser.UserID, ChatUid = clientUser.ChatUid });
                        listBoxCoustomerList.DisplayMember = "ChatUid";
                        listBoxCoustomerList.ValueMember = "UserID";
 
                        ReceseMsgGoing(txSocket, remoteEpInfo);
                    }
                    else
                    {
                        if (userinfo.Count > 0)
                        {
                            userinfo.Remove(userinfo.Where(c => c.ChatUid == remoteEpInfo).FirstOrDefault());
                            //移除下拉框对于的socket或者叫用户
                        }
                        break;
                    }
                }
                catch (Exception)
                {
                    if (userinfo.Count > 0)
                    {
                        userinfo.Remove(userinfo.Where(c => c.ChatUid == remoteEpInfo).FirstOrDefault());
                        //移除下拉框对于的socket或者叫用户
                    }
                }
            }
 
        }
 
        /// <summary>
        /// 接受来自客服端发来的消息
        /// </summary>
        /// <param name="txSocket"></param>
        /// <param name="remoteEpInfo"></param>
        private void ReceseMsgGoing(Socket txSocket, string remoteEpInfo)
        {
 
            //退到一个客服端的时候 int getlength = txSocket.Receive(recesiveByte); 有抛异常
            Thread thread = new Thread(() =>
            {
                while (true)
                {
                    try
                    {
                        byte[] recesiveByte = new byte[1024 * 1024 * 4];
                        int getlength = txSocket.Receive(recesiveByte);
                        if (getlength <= 0) { break; }
 
                        var getType = recesiveByte[0].ToString();
                        string getmsg = Encoding.UTF8.GetString(recesiveByte, 1, getlength - 1);
                        ShowMsg(remoteEpInfo, getType, getmsg);
                    }
                    catch (Exception)
                    {
                        //string userid = userinfo.FirstOrDefault(c => c.ChatUid == remoteEpInfo)?.ChatUid;
                        listBoxCoustomerList.Items.Remove(remoteEpInfo);
                        userinfo.Remove(userinfo.FirstOrDefault(c => c.ChatUid == remoteEpInfo));//从集合中移除断开的socket
 
                        listBoxCoustomerList.DataSource = userinfo;//重新绑定下来的信息
                        listBoxCoustomerList.DisplayMember = "ChatUid";
                        listBoxCoustomerList.ValueMember = "UserID";
                        txSocket.Dispose();
                        txSocket.Close();
                    }
                }
            });
            thread.IsBackground = true;
            thread.Start();
 
        }
 
        private void ShowMsg(string remoteEpInfo, string getType, string getmsg)
        {
            textboMsg.AppendText($"\r\n{remoteEpInfo}:消息类型:{getType}:{getmsg}");
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            CheckForIllegalCrossThreadCalls = false;
            this.textBox_ip.Text = "192.168.1.101";//初始值
            this.textBox_port.Text = "50000";
        }
 
        /// <summary>
        /// 服务器发送消息,可以先选择要发送的一个用户
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSendMsg_Click(object sender, EventArgs e)
        {
            var getmSg = textBoxSendMsg.Text.Trim();
            if (string.IsNullOrWhiteSpace(getmSg))
            {
                MessageBox.Show("要发送的消息不可以为空", "注意"); return;
            }
            var obj = listBoxCoustomerList.SelectedItem;
            int getindex = listBoxCoustomerList.SelectedIndex;
            if (obj == null || getindex == -1)
            {
                MessageBox.Show("请先选择左侧用户的用户"); return;
            }
            var getChoseUser = obj as ChatUserInfoBase;
            var sendMsg = ServiceSockertHelper.GetSendMsgByte(getmSg, ChatTypeInfoEnum.StringEnum);
            userinfo.FirstOrDefault(c => c.ChatUid == getChoseUser.ChatUid)?.ChatSocket?.Send(sendMsg);
        }
 
        /// <summary>
        /// 给所有登录的用户发送消息,群发了
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            var getmSg = textBoxSendMsg.Text.Trim();
            if (string.IsNullOrWhiteSpace(getmSg))
            {
                MessageBox.Show("要发送的消息不可以为空", "注意"); return;
            }
            if (userinfo.Count <= 0)
            {
                MessageBox.Show("暂时没有客服端登录!"); return;
            }
            var sendMsg = ServiceSockertHelper.GetSendMsgByte(getmSg, ChatTypeInfoEnum.StringEnum);
            foreach (var usersocket in userinfo)
            {
                usersocket.ChatSocket?.Send(sendMsg);
            }
        }
 
        /// <summary>
        /// 服务器给发送震动
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSendSnak_Click(object sender, EventArgs e)
        {
            var obj = listBoxCoustomerList.SelectedItem;
            int getindex = listBoxCoustomerList.SelectedIndex;
            if (obj == null || getindex == -1)
            {
                MessageBox.Show("请先选择左侧用户的用户"); return;
            }
            var getChoseUser = obj as ChatUserInfoBase;
 
            byte[] sendMsgByte = ServiceSockertHelper.GetSendMsgByte("", ChatTypeInfoEnum.Snake);
            userinfo.FirstOrDefault(c => c.ChatUid == getChoseUser.ChatUid)?.ChatSocket.Send(sendMsgByte);
        }
 
 
    }
}

4:客服端Code:

?
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
 
namespace ChatClient
{
    using ChatCommoms;
    using System.Net;
    using System.Net.Sockets;
    using System.Threading;
 
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
 
        private void Form1_Load(object sender, EventArgs e)
        {
            CheckForIllegalCrossThreadCalls = false;
            this.textBoxIp.Text = "192.168.1.101";//先初始化一个默认的ip等
            this.textBoxPort.Text = "50000";
        }
 
        Socket clientSocket;
        /// <summary>
        /// 客服端连接到服务器
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnServicStart_Click(object sender, EventArgs e)
        {
            try
            {
                var ipstr = textBoxIp.Text.Trim();
                var portstr = textBoxPort.Text.Trim();
                if (string.IsNullOrWhiteSpace(ipstr) || string.IsNullOrWhiteSpace(portstr))
                {
                    MessageBox.Show("要连接的服务器ip和端口都不可以为空!");
                    return;
                }
                clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                clientSocket.Connect(IPAddress.Parse(ipstr), int.Parse(portstr));
                labelStatus.Text = "连接到服务器成功...!";
                ReseviceMsg(clientSocket);
 
            }
            catch (Exception)
            {
                MessageBox.Show("请检查要连接的服务器的参数");
            }
        }
        private void ReseviceMsg(Socket clientSocket)
        {
 
            Thread thread = new Thread(() =>
             {
                 while (true)
                 {
                     try
                     {
                         Byte[] byteContainer = new Byte[1024 * 1024 * 4];
                         int getlength = clientSocket.Receive(byteContainer);
                         if (getlength <= 0)
                         {
                             break;
                         }
                         var getType = byteContainer[0].ToString();
                         string getmsg = Encoding.UTF8.GetString(byteContainer, 1, getlength - 1);
 
                         GetMsgFomServer(getType, getmsg);
                     }
                     catch (Exception ex)
                     {
                     }
                 }
             });
            thread.IsBackground = true;
            thread.Start();
 
        }
 
        private void GetMsgFomServer(string strType, string msg)
        {
            this.textboMsg.AppendText($"\r\n类型:{strType};{msg}");
        }
 
        /// <summary>
        /// 文字消息的发送
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSendMsg_Click(object sender, EventArgs e)
        {
            var msg = textBoxSendMsg.Text.Trim();
            var sendMsg = ServiceSockertHelper.GetSendMsgByte(msg, ChatModels.ChatTypeInfoEnum.StringEnum);
            int sendMsgLength = clientSocket.Send(sendMsg);
        }
    }
}

5:测试效果:

c#基于WinForm的Socket实现简单的聊天室 IM

6:完整Code GitHUb下载路径 

https://github.com/zrf518/WinformSocketChat.git

7:这个只是一个简单的聊天练习Demo,待进一步完善(实现部分功能,传递的消息byte[0]为消息的类型,用来判断是文字,还是图片等等),欢迎大家指教

以上就是c#基于WinForm的Socket实现简单的聊天室 IM的详细内容,更多关于c# WinForm实现聊天室 IM的资料请关注服务器之家其它相关文章!

原文链接:https://www.cnblogs.com/Fengge518/p/14536940.html

延伸 · 阅读

精彩推荐
  • C#c# 三种方法调用WebService接口

    c# 三种方法调用WebService接口

    这篇文章主要介绍了c# 三种方法调用WebService接口的相关资料,文中示例代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下...

    逛园子$$$8982022-09-22
  • C#再聊一次C#中值类型和引用类型

    再聊一次C#中值类型和引用类型

    C#值类型,作为函数形参,形参被修改,不影响原值。这是我们在初始学习编程时需要记住的内容,我们也是一直这样践行的。...

    精益码农9862021-08-27
  • C#在winform下实现左右布局多窗口界面的方法之续篇

    在winform下实现左右布局多窗口界面的方法之续篇

    这篇文章主要介绍了在winform下实现左右布局多窗口界面的方法之续篇 的相关资料,需要的朋友可以参考下...

    梦在旅途6582021-11-14
  • C#C#中DataGridView动态添加行及添加列的方法

    C#中DataGridView动态添加行及添加列的方法

    这篇文章主要介绍了C#中DataGridView动态添加行及添加列的方法,涉及C#中DataGridView针对行与列动态操作的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考...

    我心依旧8332021-10-26
  • C#C#弹出对话框确定或者取消执行相应操作的实例代码

    C#弹出对话框确定或者取消执行相应操作的实例代码

    这篇文章主要介绍了C#弹出对话框确定或者取消执行相应操作的实例代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借...

    Code porter T33842022-10-19
  • C#C#代码实现PDF文档操作类

    C#代码实现PDF文档操作类

    本篇文章给大家介绍使用pdf文档操作C#代码,本文代码非常简单,代码附有注释,需要注意的是:需要添加itextsharp.dll引用才可以正常通过编译,感兴趣的朋...

    C#教程网3882021-11-01
  • C#积累Visual Studio 常用快捷键的动画演示

    积累Visual Studio 常用快捷键的动画演示

    在代码开发过程中,频繁的使用键盘、鼠标操作非常麻烦,影响程序的开发效率。如何操作能用键盘来操作,那就节省时间了。下面小编把我平时积累的有...

    C#教程网7542021-10-29
  • C#unity实现物体延时出现

    unity实现物体延时出现

    这篇文章主要为大家详细介绍了unity实现物体延时出现,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    Gyp郭小帅10022022-11-09