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本身在启动完线程之后马上又进入监听状态. 示 ...
随机推荐
- 理解ES6中的Promise
一.Promise的作用 在ajax请求数据的过程中,我们可以异步拿到我们想要的数据,然后在回调中做相应的数据处理. 这样做看上去并没有什么麻烦,但是如果这个时候,我们还需要做另外一个ajax请求,这 ...
- sql 语句查询 sqlserver 数据库 MAC 地址
declare @dbid int set @dbid=db_id('dbName') select distinct hostname, db_name(dbid), net_address, lo ...
- ghostscript远程代码执行漏洞复现
这两天网上ghostscript又又有漏洞信息了,但是没有poc,于是找找资料把今年8月21日的那个验证下 1.关于ghostscript Ghostscript是一套建基于Adobe.PostScr ...
- python基础 - 变量与运算符
变量与运算符 变量 定义一个变量 a = [1,2,3,4,5,6] print(a) # [1,2,3,4,5,6] 变量命名要求: 首字母不能是数字 只能包含字符数字下划线 不能是关键字 type ...
- 简易 Token 验证的实现
简易 Token 验证的实现 前言 在我们的服务器和客户端的交互中,由于我们的业务中使用 RESTful API 的形式和客户端交互,而 API 又是无状态的,无法帮助我们识别这一次和上一次的请求由谁 ...
- Axios发送请求时params和data的区别
在使用axios时,注意到配置选项中包含params和data两者,以为他们是相同的,实则不然. 因为params是添加到url的请求字符串中的,用于get请求. 而data是添加到请求体(body) ...
- arcgis api for javascript中使用proxy.jsp
当我们使用arcgis api for javascript 查询arcgis服务时,如果查询的参数很长时,通过get方式提交会查询不到结果,因为get方式提交的参数有长度限制,需要通过代理的方式使用 ...
- Djando 的 cmd命令
1.黑窗口命令 安装Django pip install django==1.11.16 -i https://pypi.doubanio.com/simple/ 创建项目 django-ad ...
- 合并多个Excel文件
这条分享来自百度经验https://jingyan.baidu.com/article/e6c8503cb6ed7ee54e1a1811.html
- 让你提前认识软件开发(31):数据库脚本中的begin与end
版权声明:本文为博主原创文章.对文章内容有不论什么意见或建议,欢迎与作者单独交流.作者QQ(微信):245924426. https://blog.csdn.net/zhouzxi/article/d ...