c#多线程网络聊天程序代码分享(服务器端和客户端)
更新时间:2020年6月25日 11:39 点击:1627
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";
}
}
}
}
上一篇: c#检测端口是否被占用的简单实例
下一篇: C# 定时器定时更新的简单实例
相关文章
C# WinForm多线程解决界面卡死问题的完美解决方案,使用BeginInvoke
问题描述:当我们的界面需要在程序运行中不断更新数据时,当一个textbox的数据需要变化时,为了让程序执行中不出现界面卡死的现像,最好的方法就是多线程来解决一个主线程来创建界...2020-06-24- 这篇文章主要介绍了c# 多线程处理多个数据的方法,帮助大家更好的理解和学习使用c#,感兴趣的朋友可以了解下...2021-03-31
- 这篇文章主要介绍了C#基于委托实现多线程之间操作的方法,实例分析了C#的委托机制与多线程交互操作的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
- 这篇文章主要介绍了C#多线程中的异常处理操作,涉及C#多线程及异常的捕获、处理等相关操作技巧,需要的朋友可以参考下...2020-06-25
- 这篇文章主要介绍了C#中异步和多线程的相关资料,帮助大家更好的理解和学习c#,感兴趣的朋友可以了解下...2021-01-16
- 多线程和异步操作两者都可以达到避免调用线程阻塞的目的,从而提高软件的可响应性。甚至有些时候我们就认为多线程和异步操作是等同的概念。但是,多线程和异步操作还是有一些区别的。而这些区别造成了使用多线程和异步操作的时机的区别...2020-06-25
- 这篇文章主要为大家详细介绍了C#多线程之Thread类,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
- 在Java中,我们可以利用多线程来最大化地压榨CPU多核计算的能力,下面这篇文章主要给大家介绍了关于java中多线程与线程池基本使用的相关资料,需要的朋友可以参考下...2021-09-13
- 第一种解决方案的原理是:将线程执行的方法和参数都封装到一个类里面。通过实例化该类,方法就可以调用属性来实现间接的类型安全地传递多个参数...2020-06-25
- 在本篇文章里小编给大家整理的是一篇关于java多线程中执行多个程序的实例分析内容,有需要的朋友们可以学习参考下。...2021-02-07
- 这篇文章主要介绍了C#多线程编程中异步多线程的实现及线程池的使用,同时对多线程的一般概念及C#中的线程同步并发编程作了讲解,需要的朋友可以参考下...2020-06-25
- 这篇文章主要介绍了Springboot实现多线程注入bean的工具类操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-27
- th.IsBackground = true解决线程问题,意思就是把线程设置为后台线程,感兴趣的朋友可以多了解下,如何有什么妙招还请多多指导哈...2020-06-25
- 这篇文章主要介绍了C#多线程编程中的锁系统(三),本本文主要说下基于内核模式构造的线程同步方式、事件、信号量以及WaitHandle、AutoResetEvent、ManualResetEvent等内容,需要的朋友可以参考下...2020-06-25
- 这篇文章主要给大家介绍了关于Java多线程实现简易微信发红包的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-01
- 这篇文章主要介绍了c#使用多线程的几种方式,通过示例学习c#的多线程使用方式,大家参考使用吧...2020-06-25
- 这篇文章主要介绍了C#多线程编程中的锁系统(四):自旋锁,本文讲解了基础知识、自旋锁示例、SpinLock等内容,需要的朋友可以参考下...2020-06-25
- 这篇文章主要为大家详细介绍了C#多线程及同步示例,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
- 这篇文章主要介绍了C#多线程ThreadPool线程池的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
- 本篇文章小编将为大家介绍,浅解关于C#的多线程,有需要的朋友可以参考一下...2020-06-25