c#多线程网络聊天程序代码分享(服务器端和客户端)
作者:
本程序使用VS2005 制作,程序分为三块,XuLIeHua类库下有我写的把结构序列化的类,还有就是服务器端和客户端
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";
}
}
}
}