在计算机通信领域,socket 被翻译为“套接字”,它是计算机之间进行通信的一种约定或一种方式。通过 socket 这种约定,一台计算机可以接收其他计算机的数据,也可以向其他计算机发送数据

套接字之间的连接过程可以分为三个步骤 :
(1)服务器监听。
(2)客户端请求。
(3)连接确认 。

c#的Socket通讯实现聊天室,支持消息与图片发送
c#实现的主要步骤:
1:第一步创建一个开始监听的Socket
2:第二步创建Ip地址和端口号对象
3:第三步让监听的Socket绑定Ip地址跟端口号
4:第四步设置监听队列
5:最后开启一个线程循环监听连接的客户端

聊天室服务器主要起到中转的作用:
当有一个 客服端发送信息或者图片过来的时候,将其发送给所有连接上的客服端

客户端将消息解析成byte数组,在byte数组第一位加上一个数用来表示发送的消息是什么类型的该怎么去解析它(目前支持:文字0,图片1),可以理解成一个简单的协议,双方之间约定好怎么封装,怎么解析内容

界面展示

代码部分展示

服务端:

  public partial class ServerSocket : Form{public ServerSocket(){InitializeComponent();}//启动服务器private void bt_start_Click(object sender, EventArgs e){try{//第一步创建一个开始监听的SocketSocket socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//第二步创建Ip地址和端口号对象IPAddress ip = IPAddress.Any;IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(this.txt_Point.Text));//第三步让监听的Socket绑定Ip地址跟端口号socketWatch.Bind(point);//设置监听队列socketWatch.Listen(int.Parse(this.tb_num.Text));Thread t = new Thread(Listen);t.IsBackground = true;t.Start(socketWatch);}catch (Exception ex){MessageBox.Show(ex.Message);}}//循环监听连接的客户端Socket socketSend;void Listen(object o){Socket socketWatch = o as Socket;while (true){//负责监听的Socket来接收客户端的连接,创建跟客户通讯的SocketsocketSend = socketWatch.Accept();//将远程的连接客服端存储字典集合SocketHelper.Intanter.dicScoket.Add(socketSend.RemoteEndPoint.ToString(), socketSend);//添加地址到下拉框与list集合中去AddCbItem(socketSend.RemoteEndPoint.ToString());AddContent(socketSend.RemoteEndPoint.ToString() + "连接成功");Thread t = new Thread(Recive);t.IsBackground = true;t.Start(socketSend);}}//循环接收发送过来的数据void Recive(object o){Socket socketSend = o as Socket;while (true){try{string str = "";//客户端连接成功后,服务器接收客服端发送过来的数据byte[] buffer = new byte[1024 * 1024 * 2];//实际接收的有效字节int r = socketSend.Receive(buffer);if (r == 0){break;}if (buffer[0] == 0){str = socketSend.RemoteEndPoint.ToString() + ":\r\n" + "   " + Encoding.UTF8.GetString(SocketHelper.Intanter.RemoveFbyte(buffer), 0, r);}else if (buffer[0] == 1){str = socketSend.RemoteEndPoint.ToString() + ":\r\n" + "   " + SocketHelper.Intanter.ShowImgByByte(SocketHelper.Intanter.RemoveFbyte(buffer));SocketHelper.Intanter.SendMessage(buffer);}byte[] newbuffer = SocketHelper.Intanter.SendMessageToClient(str);SocketHelper.Intanter.SendMessage(newbuffer);AddContent(socketSend.RemoteEndPoint.ToString() + ":" + str);}catch (Exception ex){MessageBox.Show(ex.ToString());}}}//将连接的IP添加到下拉框public void AddCbItem(string ItemName){this.BeginInvoke(new MethodInvoker(delegate{cb_IP.Items.Add(ItemName);SocketHelper.Intanter.IPItem.Add(ItemName);}));}//将接受到的内容显示出来private void AddContent(string content){this.BeginInvoke(new MethodInvoker(delegate{rtb_log.AppendText(content + " ");rtb_log.AppendText("\r\n");rtb_log.Focus();//先获取焦点rtb_log.Select(rtb_log.TextLength, 0);//选中数据末尾0个字符rtb_log.ScrollToCaret();//将滚动条移动到当前位置//记录收到的字符个数//toolStripStatusLabel1.Text += (int.Parse(toolStripStatusLabel1.Text) + content.Length).ToString();}));}//弹出客户端private void bt_Open_Click(object sender, EventArgs e){new ClientSocket().Show();}//选择连接的客户端发送数据private void bt_send_Click(object sender, EventArgs e){string msg = this.rtb_sendmsg.Text.Trim();//byte[] buffer = Encoding.UTF8.GetBytes(msg);获得用户在下拉框的IP地址//string ip = this.cb_IP.Text;//SocketHelper.Intanter.dicScoket[ip].Send(buffer);//socketSend.Send(buffer);socketSend.Send(SocketHelper.Intanter.SendMessageToClient(msg, SocketHelper.MessageType.news));}}

客户端:

  public partial class ClientSocket : Form{public ClientSocket(){InitializeComponent();}Socket socketSend;string ImageFile;private void bt_start_Click(object sender, EventArgs e){try{//创建负责通讯的Socket//第一步创建一个开始监听的SocketsocketSend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//第二步创建Ip地址和端口号对象IPAddress ip = IPAddress.Parse(this.tb_IP.Text);IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(this.tb_Point.Text));socketSend.Connect(point);//通过ip 端口号定位一个要连接的服务器端Thread t = new Thread(Recive);t.IsBackground = true;t.Start();}catch (Exception ex){MessageBox.Show(ex.Message.ToString());}}//将接受到的内容显示出来private void AddContent(string content){this.BeginInvoke(new MethodInvoker(delegate{rtb_log.AppendText(content + " ");rtb_log.AppendText("\r\n");rtb_log.Focus();//先获取焦点rtb_log.Select(rtb_log.TextLength, 0);//选中数据末尾0个字符rtb_log.ScrollToCaret();//将滚动条移动到当前位置//记录收到的字符个数//toolStripStatusLabel1.Text += (int.Parse(toolStripStatusLabel1.Text) + content.Length).ToString();}));}void Recive(){while (true){try{//客户端连接成功后,服务器接收客服端发送过来的数据byte[] buffer = new byte[1024 * 1024 * 2];//实际接收的有效字节int r = socketSend.Receive(buffer);if (r == 0){break;}if (buffer[0] == 0){string str = Encoding.UTF8.GetString(SocketHelper.Intanter.RemoveFbyte(buffer), 0, r - 1);AddContent(str);}else if (buffer[0] == 1){string ImageName = SocketHelper.Intanter.ShowImgByByte(SocketHelper.Intanter.RemoveFbyte(buffer));AddCbItem(ImageName);}}catch (Exception ex){MessageBox.Show(ex.ToString());}}}//将接收的图片放到listview里面public void AddCbItem(string ItemName){this.BeginInvoke(new MethodInvoker(delegate{ltb_Image.Items.Add(ItemName);SocketHelper.Intanter.IPItem.Add(ItemName);}));}private void bt_send_Click(object sender, EventArgs e){try{string msg = $"  " + this.tb_name.Text + " :" + this.rtb_sendmsg.Text.Trim();socketSend.Send(SocketHelper.Intanter.SendMessageToClient(msg, SocketHelper.MessageType.news));}catch (Exception ex){MessageBox.Show(ex.ToString());}}private void bt_OpeImage_Click(object sender, EventArgs e){OpenFileDialog fileDialog = new OpenFileDialog();DialogResult result = fileDialog.ShowDialog();if (result == DialogResult.OK){this.pt_Image.Image = Image.FromFile(fileDialog.FileName);ImageFile = fileDialog.FileName;}}private void bt_SendImage_Click(object sender, EventArgs e){if (ImageFile != null && ImageFile != ""){socketSend.Send(SocketHelper.Intanter.SendMessageToClient(ImageFile, SocketHelper.MessageType.picture));}else{MessageBox.Show("未选择图片");}}private void ltb_Image_SelectedIndexChanged(object sender, EventArgs e){if (this.ltb_Image.SelectedItem == null){return;}string FileName = this.ltb_Image.SelectedItem.ToString();this.pt_Image.Image = Image.FromFile(Environment.CurrentDirectory + "\\Images\\" + FileName);// Image.FromFile(fileDialog.FileName);}}

SocketHelper类

 public class SocketHelper{//将远程连接过来的客服端的IP地址和Socket存入集合public static SocketHelper Intanter = new SocketHelper();public Dictionary<string, Socket> dicScoket = new Dictionary<string, Socket>();public List<string> IPItem = new List<string>();//消息类型枚举public enum MessageType{news,picture}/// <summary>///  服务端接收数据后将数据发送给所有的客户端/// </summary>/// <param name="buffer">发送的消息字节</param>/// <param name="ms">消息类型</param>/// <returns></returns>public void SendMessage(byte[] buffer){//获得用户在下拉框的IP地址var task1 = new Task(() =>{for (int i = 0; i < IPItem.Count; i++){string ip = IPItem[i].ToString();dicScoket[ip].Send(buffer.ToArray());}});task1.Start();}/// <summary>///  将消息转换成消息协议格式/// </summary>/// <param name="buffer">发送的消息字节</param>/// <param name="ms">消息类型</param>/// <returns></returns>public byte[] SendMessageToClient(string message, MessageType ms = MessageType.news){List<byte> newbuffer = new List<byte>();byte[] buffer = new byte[0];switch (ms){case MessageType.news:newbuffer.Add(0);buffer = Encoding.UTF8.GetBytes(message);break;case MessageType.picture:newbuffer.Add(1);buffer = SaveImage(message);break;default:break;}newbuffer.AddRange(buffer);return newbuffer.ToArray();}public byte[] RemoveFbyte(byte[] buffer){List<byte> newbuffer = buffer.ToList();newbuffer.RemoveAt(0);return newbuffer.ToArray();}/// <summary>/// 将图片以二进制流/// </summary>/// <param name="path"></param>/// <returns></returns>public byte[] SaveImage(String path){FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read); //将图片以文件流的形式进行保存BinaryReader br = new BinaryReader(fs);byte[] imgBytesIn = br.ReadBytes((int)fs.Length); //将流读入到字节数组中return imgBytesIn;}/// <summary>/// 现实二进制流代表的图片/// </summary>/// <param name="imgBytesIn"></param>public string ShowImgByByte(byte[] imgBytesIn){lock (this){string NewImageName = DateTime.Now.ToString("yyyy-mm-dd hh-mm-ss") + ".jpg";//ImageName(CenterId);//获得图片的名字string ImagePath = Environment.CurrentDirectory + $"\\Images\\";//@"F:/AQPXImageURL/" + NewImageName.ToString() + ".jpg";if (!Directory.Exists(ImagePath)){DirectoryInfo directoryInfo = new DirectoryInfo(ImagePath);directoryInfo.Create();}ImagePath += NewImageName.ToString();if (File.Exists(ImagePath)){return NewImageName;}MemoryStream ms = new MemoryStream(imgBytesIn);Bitmap bmp = new Bitmap(ms);bmp.Save(ImagePath, ImageFormat.Bmp);ms.Close();return NewImageName;}//return NewImageName;//pictureBox1.Image = Image.FromStream(ms);}}

最后如果感兴趣的可以试着将代码进行优化升级,如:实现各种类型的文件发送(将消息头经过你自己个人的封装解析),希望能帮助到大家对socket的学习
附源码:c#socket通讯源码

c#的Socket实现多人聊天室(附源码)相关推荐

  1. 类似QQ聊天软件也能用Java实现啦!(多人聊天原理附源码)

    多人聊天室原理图 源码 工具类: 该类用于关闭各种流. public class CloseUtil {public static void CloseAll(Closeable... closeab ...

  2. java socket多人聊天室_如何运用Java socket实现多人聊天室功能

    如何运用Java socket实现多人聊天室功能 导语:如何运用Java socket实现多人聊天室功能呢?下面是小编给大家提供的代码实现,大家可以参考阅读,更多详情请关注应届毕业生考试网. 目录结构 ...

  3. java socket多人聊天_如何运用Java socket实现多人聊天室功能

    导语:如何运用Java socket实现多人聊天室功能呢?下面是小编给大家提供的代码实现,大家可以参考阅读,更多详情请关注应届毕业生考试网. 目录结构: ChatClient: package com ...

  4. 聊聊语音聊天室app源码实时音视频中的技术难点:回声消除+噪声消除

    聊聊语音聊天室app源码实时音视频中的技术难点:回声消除+噪声消除 在聊聊语音聊天室app源码各个实时音视频互动场景中,回声和噪声对于影响用户体验而言都是很大的问题.音视频正在发展成为互联网线上沟通的 ...

  5. 聊天室软件源码开发中,该如何实现多线程同步?

    问题背景 在聊天室软件源码开发中,需执行多线程任务:任务1.任务2并行执行:等全部执行完成后,执行任务3. // 每个 任务 通过 sleep 模拟耗时 val task1: () -> Str ...

  6. PHP匿名在线聊天室系统源码 自适应PC+WAP端

    介绍: PHP匿名在线聊天室系统源码 自适应PC+WAP端 可发语音.图片 修改数据库config\settings.php可拿去搭建专门跟客户聊天的网站 网盘下载地址: http://kekewl. ...

  7. PHP匿名在线聊天室系统源码

    PHP匿名在线聊天室系统源码,自适应PC+WAP端,可发 语音.图片.带有三套主题模板,完美可用. [完整源码链接] PHP匿名在线聊天室系统源码.zip-PHP文档类资源-CSDN文库

  8. 分享66个PHP聊天室类源码,总有一款适合您

    分享66个PHP聊天室类源码,总有一款适合您 66个PHP聊天室类源码下载链接:https://pan.baidu.com/s/1_Fbbc3WMVWN7jjgTRaCnXw?pwd=h75j 提取码 ...

  9. Anlin-chat多功能聊天室php源码下载,极速安装

    一.名称:Anlin-chat多功能聊天室php源码 二.简介(作用): 可修改成 网站客服系校园站 统 可盈利,利用打赏.VIP.内容付费.广告盈利.资源付费等方法盈利. 三.下载地址: 聊天室zi ...

  10. 零基础搭建iOS语音聊天室平台源码

    语音聊天室平台源码玩法兴起,众多社交泛娱乐平台已纷纷跟进. 语音聊天室平台源码的实现,主要由业务系统和移动/Web 客户端组成.其中业务系统需要实现房间管理.麦位管理.音频流和麦位关联关系管理等功能, ...

最新文章

  1. Swift3.0带来的变化汇总
  2. R语言分类模型:逻辑回归模型LR、决策树DT、推理决策树CDT、随机森林RF、支持向量机SVM、Rattle可视化界面数据挖掘、分类模型评估指标(准确度、敏感度、特异度、PPV、NPV)
  3. 基于FPGA的IP核RAM的设计和调用
  4. 客户端向服务端传送特殊字符解决方法(检测到有潜在危险的 Request.Form 值)
  5. 大学医用计算机答案,医学文献检索试题(含答案)
  6. 坚持打造最好的日期控件,My97 DatePicker 4.8 Beta3
  7. 计算机专业颈椎有问题,出现这4个表现,你的颈椎病已经很严重了!上班族尤需警惕_39健康网...
  8. php curl重用,使用PHP CURL解析负载较重的站点?
  9. 贺利坚老师汇编课程47笔记:转移地址在寄存器或内存里
  10. CodeVS 1576 最长严格上升子序列 (DP)
  11. Oracle and MS SQL Server 2005
  12. WP8.1开发:简单的天气预报应用
  13. python批量修改及创建txt
  14. 论文结尾标注的引用的参考文献批量导入Endnote
  15. matlab两张图片合成一张_如何将多幅图合并在一起变成一张大图
  16. 怎么做动态文字闪图?教你一键在线做闪图
  17. 信息系统项目管理师(2022年)—— 重点内容:项目合同管理(13)
  18. 奖客富翁系统代码C语言,木马代码-c语言木马代码,最简单的,我保证不做违法的 – 手机爱问...
  19. syslog默认端口_什么是Syslog默认端口和安全端口以及如何配置它?
  20. java opencv 模板匹配算法_OpenCV探索之路(九):模板匹配

热门文章

  1. 九轴姿态传感器的介绍和应用
  2. 计算机软件需要什么配置的电脑,需要使用CAD等绘图软件需要什么配置的电脑?...
  3. 正版sql服务器,SQL Server2014企业版 授权许可 正版sql数据库
  4. W10安装NoteBook(一个Python笔记软件)及使用方法
  5. Apache Commons Lang3 DateUtils用法
  6. NXP的MSCAN模块波特率设置
  7. GA/T1400文档请求失败消息返回提
  8. Day01_操作系统概述
  9. 数据结构 计算机网络,考研数据结构和计算机网络怎么复习?
  10. JMETER之察看结果树(只显示报错请求)