1:在服务端创建了一个负责监听的sokcet

  //三个:采用TCP协议.

             ListenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            IPAddress ipAddress = IPAddress.Parse(this.txtIP.Text);//获取IP地址.

            IPEndPoint point = new IPEndPoint(ipAddress, Convert.ToInt32(this.txtPort.Text));

//通信节点.包含了IP地址与端口号.

            ListenSocket.Bind(point);//将通信节点(IP地址与端口号)与负责监听的Socket进行绑定。

        ListenSocket.Listen(10);//设置监听队列.(将当前的Socket设置侦听状态)

2:解决服务端Accept方法占用UI线程的问题.(必做)

ThreadStart start = new ThreadStart(AcceptConnection);

            Thread thread = new Thread(start);

            thread.IsBackground = true;

//设置后台线程.如果整个的服务端窗体关闭,也就没有必要再等带客户端了,

所以在这里把该线程设置为后台线程。

            thread.Start();

3:解决多个客户端请求,针对不同的客户端创建单独的newSocket(可选)

  public void AcceptConnection()

        {

            while (true)//由于每个客户端必须都有一个单独的newSocket实例与之进行交流,

所以我们服务端得Accept()方法一致等待客户端有没有链接过来。

            {

                Socket newSocket = ListenSocket.Accept();

//获取到一个客户端的请求,创建一个新的Socket,负责与客户端进行交流

。每个客户都要创建一个单独的newSocket.

                ShowMsg("客户端链接成功");

            }

        }

4:客户端怎样连接了服务端.

在客户端中添加如下代码:

   Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            IPAddress ipAddress = IPAddress.Parse(this.txtIP.Text);//获取IP地址.

            IPEndPoint endPoint = new IPEndPoint(ipAddress,Convert.ToInt32(this.txtPort.Text));

            //clientSocket.Bind(endPoint);

            clientSocket.Connect(endPoint);//客户端根据通信节点去链接服务端。在客户端不能进行Bind操作.

5:服务端怎样向客户端发送文本数据.

首先在服务添加如下代码

/// <summary>

        /// 服务端向客户端发送文本数据(发送按钮)

        /// </summary>

        /// <param name="sender"></param>

        /// <param name="e"></param>

        private void btnSendMsg_Click(object sender, EventArgs e)

        {

            string sendMsg = this.txtSendMsg.Text;

            byte[] buffer=System.Text.Encoding.UTF8.GetBytes(sendMsg);//send发送的是字节数组.

            newSocket.Send(buffer);//服务端向客户端发送数据.

            ShowMsg("发送成功!");

        }

以上代码中我们将newSocket定义了一个全局变量,这样会有问题。

客户端的代码(放在了客户端的 private void btnStartListen_Click(object sender, EventArgs e)方法中)

            byte[] buffer=new byte[1024*1024*2];

            clientSocket.Receive(buffer);

//接收服务端发过来的数据,该法会让客户端的Socket一直处于一种接收状态。

所以该方法也会占用UI线程。

            string receiveMsg=System.Text.Encoding.UTF8.GetString(buffer);

            ShowMsg(receiveMsg);

6:解决客户端接收数据的Receive方法占用UI线程问题,以及newSocket全局问题

客户端解决Receive占用UI线程问题。

            ThreadStart start = new ThreadStart(ReciveClient);

//解决客户端接收Receive方法占用UI线程的问题。

            Thread thread = new Thread(start);

            thread.IsBackground = true;

            thread.Start();

  public void ReciveClient()

        {

             *  * ];

            clientSocket.Receive(buffer);

//接收服务端发过来的数据,该法会让客户端的Socket一直处于一种接收状态。

所以该方法也会占用UI线程。

            string receiveMsg = System.Text.Encoding.UTF8.GetString(buffer);

            ShowMsg(receiveMsg);

        }

7:解决newSocket全局问题

//将与客户端进行数据交流的newSocket放入该集合中。

        Dictionary<string, Socket> dictSocket = new Dictionary<string, Socket>();

        public void AcceptConnection()

        {

            while (true)//由于每个客户端必须都有一个单独的newSocket实例与之进行交流,

所以我们服务端得Accept()方法一致等待客户端有没有链接过来。

            {

              Socket   newSocket = ListenSocket.Accept();//获取到一个客户端的请求,

创建一个新的Socket,负责与客户端进行交流。每个客户都要创建一个单独的newSocket.

              //将每个与客户端进行交流的newSocket添加到集合中,

我们用远程的客户端的IP地址与端口号作为集合的key.

              dictSocket.Add(newSocket.RemoteEndPoint.ToString(), newSocket);

                //将客户端的IP地址与端口号放在了列表中

              this.listOnline.Items.Add(newSocket.RemoteEndPoint.ToString());

                ShowMsg("客户端链接成功");

            }

        }

  /// <summary>

        /// 服务端向客户端发送文本数据

        /// </summary>

        /// <param name="sender"></param>

        /// <param name="e"></param>

        private void btnSendMsg_Click(object sender, EventArgs e)

        {

            string sendMsg = this.txtSendMsg.Text;

            byte[] buffer=System.Text.Encoding.UTF8.GetBytes(sendMsg);//send发送的是字节数组.

            string clientIp = this.listOnline.Text;

            if (!string.IsNullOrEmpty(clientIp))

            {

                //newSocket.Send(buffer);//服务端向客户端发送数据.

                //根据用户在listBox列表中选择的客户端的iP地址与端口号,找到该客户端对应的newSocket.

                dictSocket[clientIp].Send(buffer);

                ShowMsg("发送成功!");

            }

            else

            {

                MessageBox.Show("请选择要发送的客户端");

            }

        }

8:客户端一直处于接收状态.

while (true)//也要让客户端一直处于接收状态.(只是增加了改循环)

            {

                 *  * ];

                clientSocket.Receive(buffer);

//接收服务端发过来的数据,该法会让客户端的Socket一直处于一种接收状态。

所以该方法也会占用UI线程。

                string receiveMsg = System.Text.Encoding.UTF8.GetString(buffer);

                ShowMsg(receiveMsg);

            }

9:解决回车换行问题.

public void ReciveClient()

        {

            while (true)//也要让客户端一直处于接收状态.

            {

                 *  * ];

                int receiveLength=clientSocket.Receive(buffer);

//接收服务端发过来的数据,该法会让客户端的Socket一直处于一种接收状态

。所以该方法也会占用UI线程。

                //如果接收的服务端发过来的数据不足2M,那么剩余的存储单元都用"\0"来填充,

而"\0"表示字符串的结束,所以我们在接受的字符串后面加回车换行时无效。

              // string receiveMsg = System.Text.Encoding.UTF8.GetString(buffer);

                //sokecet中的Receive方法会将接收到的数据填充到字节数组中,同时返回一个整数,

表示实际接收的数据长度。那么我们在将字节数组转成字符串时,从字节数组中的第一位开始,

一直实际接收的数据长度接收。这时不包含\0,

                , receiveLength);

                ShowMsg(receiveMsg);

            }

}

数往知来 asp.net 聊天室问题解决方案<十六>的更多相关文章

  1. 学习ASP.NET Core Razor 编程系列十六——排序

    学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...

  2. ASP.NET Core 2.2 : 二十六. 应用JWT进行用户认证

    本文将通过实际的例子来演示如何在ASP.NET Core中应用JWT进行用户认证以及Token的刷新方案(ASP.NET Core 系列目录) 一.什么是JWT? JWT(json web token ...

  3. ASP.NET Core 2.2 : 二十六. 应用JWT进行用户认证及Token的刷新

    来源:https://www.cnblogs.com/FlyLolo/p/ASPNETCore2_26.html 本文将通过实际的例子来演示如何在ASP.NET Core中应用JWT进行用户认证以及T ...

  4. Asp.Net Web API 2第十六课——Parameter Binding in ASP.NET Web API(参数绑定)

    导航 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.html. 本文主要来讲解以下内容: ...

  5. 学习ASP.NET Core Razor 编程系列十八——并发解决方案

    学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...

  6. SilverLight搭建WCF聊天室详细过程[转]

    http://www.silverlightchina.net/html/zhuantixilie/getstart/2011/0424/7148.html 默认节点 SilverLight搭建WCF ...

  7. 学习ASP.NET Core Razor 编程系列十九——分页

    学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...

  8. Java进阶:基于TCP通信的网络实时聊天室

    目录 开门见山 一.数据结构Map 二.保证线程安全 三.群聊核心方法 四.聊天室具体设计 0.用户登录服务器 1.查看当前上线用户 2.群聊 3.私信 4.退出当前聊天状态 5.离线 6.查看帮助 ...

  9. ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(十四)之漏掉的客服消息

    前言 不知不觉已经十四篇了,其实已经没有什么可写了.但是突然发现layim中带的客服功能没有用到.于是乎,抽点时间完成吧.其实之前的工作已经把客服功能完成了一大半,剩下的我们稍微调整即可.今天的演示我 ...

随机推荐

  1. c# 计算一个整型数组的平均

    一个整型数组的平均: class Program { static void Main(string[] args) { ,,,,,,,,,}; double avg= GetAvg(array); ...

  2. flex 实时更新的一些方法总结

    诚为大家所知,Flash之所以优秀,就是它可以带来良好的用户体验和交互特性.既然涉及到交互性,开发人员在开发过程中必然会遇到实时更新的问题,那么,当后台数据发现变化的时候,如何让Flash端实时刷新显 ...

  3. js中Number

    var numberObject=new Number(1333);numberObject.valueOf(); 1333 var numberObject=new Number(1333);num ...

  4. VMware虚拟机中的常用文件介绍

    虚拟机的文件管理由VMware Workstation来执行.一个虚拟机一般以一系列文件的形式储存在宿主机中,这些文件一般在由workstation为虚拟机所创建的那个目录中. 如下图所示:(< ...

  5. tuning 02 Diagnostic and Tuning Tools

    statspack 是一个很重要的工具, 这是我们重点要知道的在这章 每天一上班就要看一下 alert log 文件, 可以通过/ORA找, 这是vi的知识,所有的ORACLE错误都是以ORA开头的 ...

  6. WP7应用版本升级的实现方法

    首先必须要有一个服务提供升级推送查询 // Code to execute when the application is launching (eg, from Start)         //  ...

  7. FireMonkey 平台初探

    最为第一个本地化跨平台的框架:FireMonkey需要处理以及融合不同平台的技术非常之多,所以目前的测试仅仅在于表面现象,至于效率问题还不得而知. 从一个程序员的角度来看这个框架,我觉得有以下这些方面 ...

  8. UVa 1609 (博弈) Foul Play

    姑且把它归类为一道博弈吧,毕竟这也是在找必胜方案. 十分有意思的一道题目,设计一种方案让你支持的1队获胜. 题目给出了两个很重要的条件: 1队能打败至少一半的队伍 对于1队不能打败的黑队,一定存在一个 ...

  9. scala学习笔记(6):闭包

    到本章这里,所有函数文本的例子仅参考了传入的参数.例如,(x: Int) => x > 0里,函数体用到的唯一变量,x > 0,是x,被定义为函数参数.然而也可以参考定义在其它地方的 ...

  10. XE7 - Image的双击事件无响应,咋整?(已解决)

    今天折腾了好一会,本想做个类似于手机相册的功能,显示SQLite数据库中的图片,然后继续做一些处理.哪成想,写个测试例子时就被卡住了:简单的往窗体上拖放了一个TImage和一个TLabel,没有修改任 ...