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本身在启动完线程之后马上又进入监听状态. 示 ...
随机推荐
- Appium初识
一. Appium工作原理 基本工作流程如下: Appium提供了一套web服务,Appium起一个Server(4723端口),用于与脚本client通信. server接收web driver(即 ...
- [20170705]理解linux su命令.txt
[20170705]理解linux su命令.txt --//我一般在维护时经常使用root用户登录,然后su - oracle 转到其他用户操作--//一般都加入 - 参数.这个已经成了条件反射.. ...
- redis-4.0.11主从配置初步探究
redis-4.0.11相较于以前版本,新增了几个安全措施,稍稍研究了6379.conf配置文件,在这里记录一下. 实验环境: centos7.4 redis:redis-4.0.11 1. redi ...
- python第五十三天--进程,协程.select.异步I/O...
进程: #!usr/bin/env python #-*-coding:utf-8-*- # Author calmyan import multiprocessing,threading,time ...
- 【PAT】B1071 小赌怡情(15 分)
水题一道,直接贴代码 #include<cstdio> #include<string.h> int main(){ //玩家的筹码数.以及 int T,K;scanf(&qu ...
- MySQL基本简单操作01
MySQL基本简单操作 学会了安装Docker,那么就将它利用起来.(/滑稽脸) 之前想学习Mysql(Windows下配置真麻烦),学会了Docker就方便了,直接使用Docker创建一个Mysql ...
- strong vs copy
一.前言 在这里,我通过实例去介绍strong和copy的区别(%p打印出来对象的地址) ViewController.h #import <UIKi ...
- 17秋 软件工程 团队第五次作业 Alpha Scrum8
17秋 软件工程 团队第五次作业 Alpha Scrum8 今日完成的任务 世强:部门人员管理界面设计编写: 港晨:设计主页面: 树民:web后端框架与前端对接: 伟航:app前端界面的美工: 陈翔: ...
- IO流(字节流,字符流,缓冲流)
一:IO流的分类(组织架构) 根据处理数据类型的不同分为:字节流和字符流 根据数据流向不同分为:输入流和输出流 这么庞大的体系里面,常用的就那么几个,我们把它们抽取出来,如下图: 二:字符字节 ...
- 解决input框黄色背景问题(转)
input:-webkit-autofill { box-shadow: 0 0 0px 1000px white inset !important;} <form action="l ...