Socket入门笔记 用TcpClient实现一个简易聊天室
效果

实现思路
使用TcpListener建一个服务器,接收所有客户端发送的消息,然后由服务器再发送到其他客户端
客户端使用TcpClient,发消息给服务器,接收服务器的消息,不和其他客户端直接交互
服务器端
接收客户端
开启一个线程,死循环去接收客户端.接收到之后放到一个集合里,保存起来,以便转发消息用.每个客户端都再开启一个线程,用于接收这个客户端发送的消息.
接收客户端的方法AcceptTcpClient()是阻塞方法,在程序退出释放资源时会引发异常,可以先使用Pending()方法先判断是否有挂起的链接请求,有请求的话再去接收.这样可以避免退出时引发的异常.
这里取每隔1秒接收一次.
/// <summary>
/// 接收客户端
/// </summary>
private void AcceptClient()
{
try
{
while (_isAccept)
{
if (_listener.Pending())
{
TcpClient client = _listener.AcceptTcpClient();
IPEndPoint endpoint = client.Client.RemoteEndPoint as IPEndPoint;
_clients.Add(endpoint.ToString(), client);
//添加到前端客户端列表
lbx_Clients.Dispatcher.Invoke(() =>
{
lbx_Clients.Items.Add(endpoint.ToString());
});
//接收消息线程
Thread reciveMessageThread = new Thread(ReciveMessage);
reciveMessageThread.Start(client);
}
else
{
Thread.Sleep();
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
接收消息并转发
也是死循环接收,使用Read()方法接收.如果远程主机已关闭连接,Read()将立即返回零字节.此时跳出循环,释放资源,结束此线程.
/// <summary>
/// 接收消息
/// </summary>
/// <param name="obj">TcpClient</param>
private void ReciveMessage(object obj)
{
TcpClient client = obj as TcpClient;
IPEndPoint endpoint = null;
NetworkStream stream = null;
try
{
endpoint = client.Client.RemoteEndPoint as IPEndPoint;
stream = client.GetStream();
while (true)
{
];
//如果远程主机已关闭连接,Read将立即返回零字节
, data.Length);
)
{
#region if
, length);
//添加到前端消息列表
lbx_Messages.Dispatcher.Invoke(() =>
{
lbx_Messages.Items.Add(string.Format("{0}:{1}", endpoint.ToString(), msg));
});
//发送到其他客户端
foreach (KeyValuePair<string, TcpClient> kvp in _clients)
{
if (kvp.Value != client)
{
string writeMsg = string.Format("{0}:{1}", endpoint.ToString(), msg);
byte[] writeData = Encoding.UTF8.GetBytes(writeMsg);
NetworkStream writeStream = kvp.Value.GetStream();
writeStream.Write(writeData, , writeData.Length);
}
}
#endregion
}
else
{
//客户端断开连接 跳出循环
break;
}
}
}
catch (Exception ex)
{
//Read是阻塞方法 客户端退出是会引发异常 释放资源 结束此线程
}
finally
{
//从前端客户端列表移除
lbx_Clients.Dispatcher.Invoke(() =>
{
lbx_Clients.Items.Remove(endpoint.ToString());
});
//释放资源
stream.Dispose();
_clients.Remove(endpoint.ToString());
client.Dispose();
}
}
客户端
接收消息
开启线程,死循环接收服务器发送的消息.如果Read()返回0,说明服务器已关闭.
/// <summary>
/// 接收消息
/// </summary>
private void ReciveMessage()
{
try
{
NetworkStream stream = _client.GetStream();
while (true)
{
];
, data.Length);
)
{
, length);
//添加到前端消息列表
lbx_Messages.Dispatcher.Invoke(() =>
{
lbx_Messages.Items.Add(msg);
});
}
else
{
MessageBox.Show("服务器已关闭");
stream.Dispose();
break;
}
}
}
catch (Exception ex)
{
//Read是阻塞方法 程序退出释放资源是会引发异常 不做处理 线程结束
}
}
源码下载:
服务器端:SocketServerDemo.zip
Socket入门笔记 用TcpClient实现一个简易聊天室的更多相关文章
- Python开发【笔记】:aiohttp搭建简易聊天室
简易聊天室: 1.入口main.py import logging import jinja2 import aiohttp_jinja2 from aiohttp import web from a ...
- vue + socket.io实现一个简易聊天室
vue + vuex + elementUi + socket.io实现一个简易的在线聊天室,提高自己在对vue系列在项目中应用的深度.因为学会一个库或者框架容易,但要结合项目使用一个库或框架就不是那 ...
- 真刀实战地搭建React+Webpack+Express搭建一个简易聊天室
一.前面bb两句 因为自惭(自残)webpack配置还不够熟悉,想折腾着做一个小实例熟悉.想着七夕快到了,做一个聊天室自己和自己聊天吧哈哈.好了,可以停止bb了,说一下干货. 二. 这个项目能学到啥? ...
- 原生NodeJs制作一个简易聊天室
准备工作 安装NodeJs环境 安装编译器Sublime 如果网速不理想,可以百度一下如何加快npm的速度~ 使用node搭建一个简单的网站后台 做完准备工作之后,新建文件夹chatroom,在cha ...
- Socket实现简易聊天室,Client,Server
package seday08; import java.io.BufferedWriter;import java.io.OutputStream;import java.io.OutputStre ...
- node+websocket创建简易聊天室
关于websocket的介绍太多,在这就不一一介绍了,本文主要实现通过websocket创建一个简易聊天室,就是90年代那种聊天室 服务端 1.安装ws模块,uuid模块,ws是websocket模块 ...
- node.js+websocket实现简易聊天室
(文章是从我的个人主页上粘贴过来的,大家也可以访问我的主页 www.iwangzheng.com) websocket提供了一种全双工客户端服务器的异步通信方法,这种通信方法使用ws或者wss协议,可 ...
- php_D3_“简易聊天室 ”实现的关键技术 详解
PHP+MySQL实现Internet上一个简易聊天室的关键技术 系统目标: 聊天室使用数据库汇集每个人的发言,并可将数据库内的发言信息显示在页面,让每个用户都可 ...
- 示例:Socket应用之简易聊天室
在实际应用中,Server总是在指定的端口上监听是否有Client请求,一旦监听到Client请求,Server就会启动一个线程来响应该请求,而Server本身在启动完线程之后马上又进入监听状态. 示 ...
随机推荐
- 兼容多种模块规范(AMD,CMD,Node)的代码
在JavaScript模块化开发中,为了让同一个模块可以运行在前后端,以及兼容多种模块规范(AMD,CMD,Node),类库开发者需要将类库代码包装在一个闭包内. AMD规范 AMD,即“异步模块定义 ...
- MySQL8的注意点
最近使用MySQL8,发现两个问题,略记如下: 1. 新建用户无法使用JDBC或者Navicat等登陆,报错信息为 认证失败 ,原因为 新版 MySQL 认证插件变化(变为caching_sha2_p ...
- CSS| 學習心得
resize :both , 只有overflow設置為auto時, 才能起作用???
- AD域自定义属性《完整》
1.安装Active Directory 架构,下载:adminpak.msi安装. 2.以管理员运行cmd,执行:regsvr32 schmmgmt.dll(该命令将在计算机上注册“schmmgmt ...
- VMware导入OVF时报错(未能部署OVF包用户取消了任务的解决办法)
阅读目录: 1.问题 2.原因 3.解决方案 问题:部署OVF模版的时候报错“用户取消了任务” 原因:导出ovf模板时,虚拟CD-ROM的选项要选[客户端设备],否则导入时报错“用户取消了任务” 解决 ...
- VM虚拟机打不开,没有反应,解决方法。
最近的项目开发,需要用到虚拟机,但是打开虚拟机VM8却发现,以前创建的虚拟机都用不了,点击左侧[我的计算机]中的虚拟机列表,没有任何反应,也没有任何错误提示,服务中所有的虚拟机服务都开启了,网上百度没 ...
- 7.1Python异常处理
目录 目录 前言 (一)常见的异常 (二)异常的处理 ==1.异常的预防:== ==2.解决已经知道类型的异常== ==3.合并处理多个异常== ==4处理未知类型的异常== (三)with语句 目录 ...
- 手把手实战:eclipse 搭建 SpringMvc 框架环境
环境准备 eclipse jdk1.8 tomcat 7 步骤总纲 a.准备好开发环境 b.下载相关jar包 c.在eclipse 中创建好工程 d.引进下载的ja ...
- MYSQL中的int(11)到底代表什么意思?
对于int类型的一些基础知识其实上图已经说的很明白了,在这里想讨论下常用的int(11)代表什么意思,很长时间以来我都以为这代表着限制int的长度为11位,直到有天看到篇文章才明白,11代表的并不是长 ...
- yii2查询汇总
页面输出list信息 return $this->render('index', [ 'model' => $model, 'cats' => $cats, 'findlist' = ...