c#多线程网络聊天程序代码分享(服务器端和客户端)
发布时间:2022-08-10 00:32:48
标签:多线程,网络聊天程序
XuLIeHua类库
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace XuLIeHua
{
[Serializable]
public struct NetMsg
{
public IPAddress Fip; //发送者的IP。
public string msg; //发送的消息。
public IPAddress JieIP; //接收者的ip。
public int port; //端口。
}
public class XuLIe
{
/// <summary>
/// 序列化
/// </summary>
/// <param ></param>
/// <returns></returns>
public static byte[] ObjToByte(object obj)
{
byte[] tmp = null;
MemoryStream fs = new MemoryStream();
try
{
BinaryFormatter Xu = new BinaryFormatter();
Xu.Serialize(fs, obj);
tmp = fs.ToArray();
}
catch (Exception err)
{
throw err;
}
finally
{
fs.Close();
}
return tmp;
}
/// <summary>
/// 反列化
/// </summary>
/// <param ></param>
/// <returns></returns>
public static object ByteToObj(byte[] tmp)
{
MemoryStream fs = null;
object obj = null;
try
{
fs = new MemoryStream(tmp);
fs.Position = 0;
BinaryFormatter Xu = new BinaryFormatter();
obj = Xu.Deserialize(fs);
}
catch (Exception err)
{
throw err;
}
finally
{
fs.Close();
}
return obj;
}
}
public class ServerJieShou
{
private static TcpClient Client;
public Thread th;
private ArrayList Arr;
private LogText log;
private bool Tiao = true;
private Timer time1;
private TimerCallback time;
public ServerJieShou(TcpClient sClient, ArrayList arr)
{
log = new LogText("连接") ;
Client = sClient;
Arr = arr;
th = new Thread(new ThreadStart(ThSub));
th.IsBackground = true;
th.Start();
time = new TimerCallback(XinTiao);
time1 = new Timer(time, null, 15000, -1);
}
private void XinTiao(object state)
{
if (Tiao == true)
{
Tiao = false;
}
else
{
Client = null;
}
}
private void ThSub()
{
try
{
while (Client != null)
{
NetworkStream Net = Client.GetStream();
if (Net.DataAvailable == true) //有数据。
{
byte[] tmp = new byte[1024];
if (Net.CanRead == true)
{
MemoryStream memory = new MemoryStream();
memory.Position = 0;
int len = 1;
while (len != 0)
{
if (Net.DataAvailable == false) { break; }
len = Net.Read(tmp, 0, tmp.Length);
memory.Write(tmp, 0, len);
}
log.LogWriter("接收完毕");
NetMsg msg = (NetMsg)XuLIe.ByteToObj(memory.ToArray());
log.LogWriter("序列化完毕");
TcpClient tcpclient = new TcpClient();
log.LogWriter("建立TCP对象");
if (msg.Fip != null) //非心跳包。
{
try
{
tcpclient.Connect(msg.JieIP, msg.port);
NetworkStream SubNet = tcpclient.GetStream();
byte[] Tmp = XuLIe.ObjToByte(msg);
SubNet.Write(Tmp, 0, Tmp.Length);
}
catch (SocketException)
{
msg.msg = "对方不在线";
byte[] Tmp = XuLIe.ObjToByte(msg);
Net.Write(Tmp, 0, Tmp.Length);
}
}
else
{
if (msg.msg == "QUIT")
{
Arr.Remove(Client);
return;
}
}
tcpclient.Close();
GC.Collect();
}
}
else //没有数据。
{
}
Thread.Sleep(1000);
}
}
catch
{
Arr.Remove(Client);
th.Abort();
}
}
}
}
日志输出类
using System;
using System.Text;
using System.IO;
using System.Windows.Forms;
namespace XuLIeHua
{
/// <summary>
/// 错误日志的输出。
/// </summary>
public class LogText
{
private string AppPath;
private StreamWriter StrW;
private string FileName;
public LogText(string FileName1)
{
AppPath = Application.StartupPath +@"\Log";
try
{
if (Directory.Exists(AppPath) == false)
{
Directory.CreateDirectory(AppPath);
}
if (File.Exists(AppPath+@"\"+FileName+".log") == false)
{
File.Create(AppPath+@"\"+FileName+".log");
}
FileName = FileName1;
}
catch{}
}
public void LogWriter(string Text)
{
try
{
StrW = new StreamWriter(AppPath+@"\"+FileName+".log",true);
StrW.WriteLine("时间:{0} 描述:{1} \r\n",DateTime.Now.ToString(),Text);
StrW.Flush();
StrW.Close();
}
catch{}
}
}
}
服务器
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Net;
using System.Threading;
using XuLIeHua;
using System.Net.Sockets;
using System.Collections;
namespace 服务器
{
public partial class frmServer : Form
{
public frmServer()
{
InitializeComponent();
}
private ArrayList arr;
private TcpListener Server1;
private TcpClient col;
private ArrayList LianJIe;
private void frmServer_Load(object sender, EventArgs e)
{
arr = new ArrayList();
LianJIe = new ArrayList();
Server1 = new TcpListener(Dns.GetHostAddresses(Dns.GetHostName())[0], 8000);
Server1.Start();
timer1.Enabled = true;
}
private void timer1_Tick(object sender, EventArgs e)
{
try
{
if (Server1.Pending() == true)
{
col = Server1.AcceptTcpClient();
arr.Add(col);
XuLIeHua.ServerJieShou server = new ServerJieShou(col, arr);
LianJIe.Add(server);
}
if (arr.Count == 0) { return; }
listBox1.Items.Clear();
foreach (TcpClient Col in arr)
{
IPEndPoint ip = (IPEndPoint)Col.Client.RemoteEndPoint;
listBox1.Items.Add(ip.ToString());
}
}
catch (Exception err)
{
MessageBox.Show(err.Message);
// Application.Exit();
}
}
private void frmServer_FormClosing(object sender, FormClosingEventArgs e)
{
try
{
foreach (XuLIeHua.ServerJieShou Col in LianJIe)
{
Col.th.Abort();
Col.th.Join();
}
foreach (TcpClient Col in arr)
{
Col.Close();
}
}
finally
{
Application.Exit();
}
}
}
}
客户端
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Net;
using System.Net.Sockets;
using XuLIeHua;
namespace 客户端
{
public partial class frmClinet : Form
{
public frmClinet()
{
InitializeComponent();
}
private TcpClient Clinet;
private NetworkStream net;
private void button3_Click(object sender, EventArgs e)
{
try
{
Clinet = new TcpClient();
Clinet.Connect(Dns.GetHostAddresses(textBox2.Text)[0], 8000);
this.Text = "服务器连接成功";
Thread th = new Thread(new ThreadStart(JieShou));
th.Start();
timer1.Enabled = true;
}
catch (SocketException)
{
Clinet.Close();
Clinet = null;
}
}
private void JieShou()
{
try
{
while(Clinet != null)
{
net = Clinet.GetStream();
if (net.CanWrite == false) { Clinet = null; return;}
if (net.DataAvailable == true)
{
byte[] tmp = new byte[1024];
MemoryStream memory = new MemoryStream();
int len = 1;
while (len != 0)
{
if (net.DataAvailable == false) { break; }
len = net.Read(tmp, 0, tmp.Length);
memory.Write(tmp, 0, len);
}
if (memory.ToArray().Length != 4)
{
NetMsg msg = (NetMsg)XuLIe.ByteToObj(memory.ToArray());
textBox1.Text += msg.Fip.ToString() + "说: " + msg.msg + "\r\n";
}
}
Thread.Sleep(200);
}
}
catch (Exception err)
{
lock (textBox1)
{
textBox1.Text = err.Message;
}
}
}
private void frmClinet_FormClosing(object sender, FormClosingEventArgs e)
{
if (net.CanWrite == true)
{
NetMsg msg = new NetMsg();
msg.msg = "QUIT";
byte[] tmp = XuLIe.ObjToByte(msg);
try
{
net.Write(tmp, 0, tmp.Length);
}
catch (IOException)
{
textBox1.Text += "已经从服务器断开连接\r\n";
Clinet.Close();
Clinet = null;
return;
}
}
Clinet = null;
GC.Collect();
Application.ExitThread();
}
private void button1_Click(object sender, EventArgs e)
{
try
{
if (Clinet != null)
{
if (net != null)
{
NetMsg msg = new NetMsg();
msg.Fip = Dns.GetHostAddresses(Dns.GetHostName())[0];
msg.JieIP = Dns.GetHostAddresses(textBox3.Text)[0];
msg.msg = textBox4.Text;
byte[] tmp = XuLIe.ObjToByte(msg);
net.Write(tmp, 0, tmp.Length);
}
}
else
{
textBox1.Text += "未与服务器建立连接\r\n";
}
}
catch (Exception)
{
textBox1.Text += "未与服务器建立连接\r\n";
}
}
private void timer1_Tick(object sender, EventArgs e)
{
try
{
if (Clinet != null)
{
if (net.CanWrite == true)
{
NetMsg msg = new NetMsg();
msg.msg = "0000";
byte[] tmp = XuLIe.ObjToByte(msg);
try
{
net.Write(tmp, 0, tmp.Length);
}
catch (IOException)
{
textBox1.Text += "已经从服务器断开连接\r\n";
Clinet.Close();
Clinet = null;
return;
}
}
}
else
{
textBox1.Text += "未与服务器建立连接\r\n";
}
}
catch (Exception err)
{
textBox1.Text += err.Message +"r\n";
}
}
}
}


猜你喜欢
- 项目常常需要有访问共享文件夹的需求,例如共享文件夹存储照片、文件等。那么如何使用Java读写Windows共享文件夹呢?Java可以使用JC
- mybatis的foreach标签经常用于遍历集合,构建in条件语句或者批量操作语句。下面是foreach标签的各个属性属性描述collec
- 1.介绍关机闹钟为Android中默认支持的功能,实现起来则需要满足一定的条件:自动开机、开机后响铃。对于自动开机来说,自动关机可以在应用层
- 一、JAVA简要概述先说一下java之父,詹姆斯·高斯林这是一个爱喝咖啡而又强大的男人。再来看一下JAVA有多火在TIOBE排行榜上JAVA
- 这篇文章主要介绍了java实现上传文件类型检测过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋
- MVC中,一般的情况下,使用IDE工具帮我们生成的代码,在路由注册的时候:public static void RegisterRoutes
- 原因如下: Delete()之后需要datatable.AccepteChanges()方法确认完全删除,因为Delete()只是将相应列的
- 本文实例为大家分享了java实现通讯录管理系统的具体代码,供大家参考,具体内容如下完成项目的流程:1.根据需求,确定大体方向 2.功能模块分
- TCP异步Socket模型C#的TCP异步Socket模型是通过Begin-End模式实现的。例如提供BeginConnect、BeginA
- 打开首页,明显看到链接是https打头,https和http的通信协议差别,在于https安全性更高:http和https的差别很明显,二者
- 模板消息文档公众号的类型分为服务号、订阅号和企业号,其中服务号和订阅号比较常见。要想实现公众号推动消息给指定的用户,其类型必须为服务号。推送
- 直接进入主题先来看一个栗子,假设现在有一个第三方dllnamespace TestLibrary1{ p
- 本文实例为大家分享了java实现按层遍历二叉树,按层遍历二叉树可以通过队列来实现。其主要思路如下:1、先将根节点放入队列中2、每次都从队列中
- 异步操作C++11为异步操作提供了4个接口std::future : 异步指向某个任务,然后通过future特性去获取任务函数的返回结果。s
- 本文实例为大家分享了Android仿IOS UIAlertView对话框的具体代码,供大家参考,具体内容如下显示效果:我在参考链接中看到了作
- 为什么要用ELKELK实际上是三个工具,Elastricsearch + Logstash + Kibana,通过ELK,用来收集日志还有进
- 数据存储与访问常用方式:文件SharedPreferences(偏好参数设置)SQLite数据库内容提供者(Content provider
- 在学习SpringBoot的过程中遇到一个问题,因为SpringBoot是集成了tomcat的,所以项目是打成jar包,通过SpringMV
- Java8的groupingBy实现集合的分组,类似Mysql的group by分组功能,注意得到的是一个map对集合按照单个属性分组、分组
- 本文实例讲述了Java swing框架实现的贪吃蛇游戏。分享给大家供大家参考,具体如下:java是门高级语言,做游戏时适合做后台,但是用它也