完整的TCP通信包实现
using System;
namespace Jh.Sockets
{
/// <summary>
/// 线程状态信号定义
/// </summary>
public enum JhThreadStatus
{
Stop, //停止
Running, //正在运行
Exit //已退出
}
/// <summary>
/// 线程状态参数
/// </summary>
class Parm
{
public Parm(object obj):this(JhThreadStatus.Stop,obj)
{
}
public Parm(JhThreadStatus nStatus,object obj)
{
Status = nStatus;
ObjParm = obj;
}
JhThreadStatus status;
object objParm;
/// <summary>
/// 上下文对象
/// </summary>
public object ObjParm
{
get
{
return objParm;
}
set
{
objParm = value;
}
}
/// <summary>
/// 控制状态
/// </summary>
public JhThreadStatus Status
{
get
{
return status;
}
set
{
status = value;
}
}
};
/// <summary>
/// 通讯数据处理接口
/// </summary>
public interface IObserver
{
//
// 数据处理入口
//
void Deal(CommData cd);
//
// 数据处理重载方法.如果不希望后面的处理者继续处理数据,则返回true,否则返回false;
//
bool OnDeal(CommData cd);
//
// 附加的自身初始化操作
//
bool Init();
//
// 提前初始化接口
//
bool BeforeInit();
//
// 初始化后处理接口
//
bool AfterInit();
//
// 删除前处理接口
//
bool BeforeExit();
//
// 下一个观察者
//
IObserver Next
{
get;
set;
}
//
// 上一个观察者
//
IObserver Prev
{
get;
set;
}
//
// 添加观察者到后面,如果已经存在链表中则不做任何操作
//
void Add(IObserver observer);
//
// 插入观察者到下一个观察者的前面
//
void Insert(IObserver observer);
//删除观察者
void Remove(IObserver observer);
//是否存在链表中
bool IsExist(IObserver observer);
}
/// <summary>
/// 通讯数据处理类的基类,只能派生
/// </summary>
public abstract class Observer : IObserver
{
/// <summary>
/// 数据处理入口.
/// </summary>
/// <param name="client">TcpClient类 实例</param>
/// <param name="s">内存数据流</param>
public void Deal(CommData cd)
{
cd.Data.Position = 0;
if (OnDeal(cd) == false) return ;
if (next != null)
{
next.Deal(cd);
}
return ;
}
/// <summary>
/// 数据处理重载方法.
/// </summary>
/// <param name="client">TcpClient类 实例</param>
/// <param name="s">内存数据流</param>
/// <returns>处理结果,如果不希望后面的处理者继续处理数据,则返回false,否则返回true;</returns>
public virtual bool OnDeal(CommData cd)
{
return true;
}
//附加的自身初始化操作
public virtual bool Init()
{
return true;
}
//提前初始化接口
public virtual bool BeforeInit()
{
return true;
}
//初始化后处理接口
public virtual bool AfterInit()
{
return true;
}
//删除前处理接口
public virtual bool BeforeExit()
{
return true;
}
//下一个观察者
IObserver next = null;
public IObserver Next
{
get
{
return next;
}
set
{
next = value;
}
}
//上一个观察者
IObserver prev = null;
public IObserver Prev
{
get
{
return prev;
}
set
{
prev = value;
}
}
//添加观察者
public void Add(IObserver observer)
{
if (this == observer) return;//已经存在
if (next == null)
{
next = observer;//达到最底端
next.Prev = this;
}
else next.Add(observer);//加到后面
}
/// <summary>
/// 插入观察者到下一个观察者的前面
/// </summary>
/// <param name="observer"></param>
public void Insert(IObserver observer)
{
//是否等于自己
if (this == observer) return;
//先查找是否已经存在链表中
if (Next != null && Next.IsExist(observer)) Next.Remove(observer);
//
observer.Next = Next;
if (Next != null) Next.Prev = observer;
Next = observer;
observer.Prev = this;
}
/// <summary>
/// 删除观察者
/// </summary>
/// <param name="observer"></param>
public void Remove(IObserver observer)
{
if (observer == this)
{
if (Prev != null) Prev.Next = Next;
if (Next != null) Next.Prev = Prev;
}
else
{
if (Next != null) Next.Remove(observer);
}
}
/// <summary>
/// 查找是否存在
/// </summary>
/// <param name="observer"></param>
/// <returns></returns>
public bool IsExist(IObserver observer)
{
if (observer == this) return true;
if (Next == null) return false;
else return Next.IsExist(observer);
}
}
/// <summary>
/// 日志处理基类,本身从通讯数据处理类的基类派生。
/// </summary>
class Log : Observer
{
public Log()
{
}
public Log(string slogfile)
{
LogFile = slogfile;
}
~Log()
{
}
// 日志文件带路径名称
private string logFile;
public string LogFile
{
get
{
return logFile;
}
set
{
logFile = value;
}
}
}
}
using System;
using System.Collections;
using System.IO;
using System.Threading;
namespace Jh.Sockets
{
/// <summary>
/// 数据集中管理类
/// </summary>
public class CommDataMgr
{
static int index = 0;
int id;
/// <summary>
/// 无参数构造方法
/// </summary>
public CommDataMgr()
{
id = index ++;
dnFlag = new Parm(this);
Console.WriteLine("JH data distributor {0} constructed",id);
}
Thread t = null;
public void Start()
{
if (dnFlag.Status != JhThreadStatus.Running)
{
dnFlag.Status = JhThreadStatus.Running;
t = new Thread (new ThreadStart(DataNotiyfyThread));
t.Name = "JH data distributing " + id.ToString();
t.Start();
Console.WriteLine("JH data distributing thread of JH data distributor {0} started",id);
}
}
public void Stop()
{
if ( dnFlag.Status == JhThreadStatus.Running )
{
lock (this)
{
dnFlag.Status = JhThreadStatus.Stop;
}
}
}
/// <summary>
/// 析构方法
/// </summary>
~CommDataMgr()
{
Stop();
Console.WriteLine("JH data distributor {0} unconstructed",id);
}
public void DataNotiyfyThread()
{
try
{
while (dnFlag.Status == JhThreadStatus.Running)
{
DealData();
Thread.Sleep(100);
// Console.WriteLine("分发线程{0}工作中",id);
}
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
finally
{
lock(this)
{
dnFlag.Status = JhThreadStatus.Exit;
}
Console.WriteLine("JH data distributing thread of JH data distributor {0} exited",id);
}
}
Parm dnFlag = null;
ArrayList aData = new ArrayList();
InnerObserver root = new InnerObserver();
/// <summary>
/// 观察者根节点类 定义
/// </summary>
internal class InnerObserver : Observer
{
}
public void DealData()
{
if (DataCount > 0)
{
lock(this)
{
if (root.Next != null)
{
root.Next.Deal((CommData)aData[0]);
}
RemoveAt(0);
}
}
}
/// <summary>
/// 未处理数据个数
/// </summary>
public int DataCount
{
get
{
return aData.Count;
}
}
/// <summary>
/// 根据索引返回未处理数据
/// </summary>
internal CommData this[int Index]
{
get
{
return (CommData)aData[Index];
}
}
/// <summary>
/// 根据索引删除数据
/// </summary>
/// <param name="Index">索引</param>
public void RemoveAt(int Index)
{
if (Index >= 0 && Index < DataCount)
{
lock (this)
{
aData.RemoveAt(Index);
}
}
}
/// <summary>
/// 接收到新的数据提交
/// </summary>
/// <param name="client">客户端连接</param>
/// <param name="s">数据流</param>
public void AddData(JhClient client,MemoryStream s,int len)
{
CommData cd = new CommData(client,s,len,this);
lock(this)
{
aData.Add(cd);
}
}
/// <summary>
/// 添加观察者
/// </summary>
/// <param name="observer"></param>
public void Add(IObserver observer)
{
lock (this)
{
root.Add(observer);
}
}
/// <summary>
/// 删除观察者
/// </summary>
/// <param name="observer"></param>
public void Remove(IObserver observer)
{
lock (this)
{
root.Remove(observer);
}
}
/// <summary>
/// 在最前面插入观察者
/// </summary>
/// <param name="observer"></param>
public void Insert(IObserver observer)
{
lock (this)
{
root.Insert(observer);
}
}
// 取观察者个数
// int GetObserverCount()
// {
// return (int)m_aObservers.GetCount();
// }
}
}
using System;
using System.Threading;
using System.Net.Sockets;
using System.IO;
using System.Collections;
using System.Windows.Forms;
using System.Net;
namespace Jh.Sockets
{
/// <summary>
/// 内部通信消息
/// </summary>
enum JhCommMessages
{
MessageStart = 9909,//消息起始
DataTransfer, //数据传输
Disconnected, //连接将要断开
ConnectSignal, //连接检查信号
ConnectCheck, //启动连接信号
StopCheck, //停止连接信号
Unknown = 9999 //未知
}
/// <summary>
/// 通信数据
/// </summary>
public class CommData
{
public CommData(JhClient client,MemoryStream stream,int len,CommDataMgr dm)
{
jhClient = client;
Data = new MemoryStream();
stream.WriteTo(Data);
dataLen = len;
adm = dm;
}
JhClient jhClient;
MemoryStream data;
int dataLen;
CommDataMgr adm;
/// <summary>
/// tcp连接
/// </summary>
public JhClient Socket
{
get
{
return jhClient;
}
}
/// <summary>
/// 内存数据流
/// </summary>
public MemoryStream Data
{
get
{
return data;
}
set
{
data = value;
}
}
/// <summary>
/// 数据长度
/// </summary>
public int DataLen
{
get
{
return dataLen;
}
}
};
public delegate void CommEventHandler(object sender,CommEventArgs e);
public class CommEventArgs : EventArgs
{
public CommEventArgs(string msg):base()
{
Message = msg;
}
string message;
public string Message
{
get
{
return message;
}
set
{
message = value;
}
}
}
/// <summary>
/// Tcp通信客户类
/// </summary>
public class JhClient
{
/// <summary>
/// 连接成功事件
/// </summary>
public event CommEventHandler OnConnected;
/// <summary>
/// 连接关闭事件
/// </summary>
public event CommEventHandler OnClosed;
/// <summary>
/// 连接失败事件
/// </summary>
public event CommEventHandler OnConnectFailed;
/// <summary>
/// 构造方法
/// </summary>
/// <param name="dm">外部植入的数据管理类</param>
/// <param name="ob">观察者</param>
/// <param name="tcpClient">通信连接</param>
public JhClient(CommDataMgr dm,IObserver ob,TcpClient tcpClient)
{
//
// TODO: 在此处添加构造函数逻辑
//
status = new Parm(this);
checkStatus = new Parm(this);
autoConnectStatus = new Parm(this);
if (dm == null)
{
adm = new CommDataMgr();
}
else adm = dm;
if (ob != null) adm.Add(ob);
if (tcpClient == null)
{
client = new TcpClient();
}
else client = tcpClient;
ID = index ++;
OnClosed += new CommEventHandler(OnConnectClosed);
Console.WriteLine("JH tcp client {0} constructed",ID);
}
static int index = 0;
/// <summary>
/// 无参数构造函数
/// </summary>
public JhClient(TcpClient tcpClient) : this(null,null,tcpClient)
{}
public JhClient(CommDataMgr dm,TcpClient tcpClient) : this(dm,null,tcpClient)
{}
public JhClient(IObserver ob,TcpClient tcpClient):this(null,ob,tcpClient)
{}
public JhClient() : this(null,null,null)
{}
public JhClient(CommDataMgr dm) : this(dm,null,null)
{}
public JhClient(IObserver ob):this(null,ob,null)
{}
/// <summary>
/// 析构方法
/// </summary>
~JhClient()
{
AutoConnect = false;
ConnectCheck = false;
Close();
Console.WriteLine("JH tcp client {0} unconstructed",ID);
}
Parm status = null;
/// <summary>
/// 唯一标志符
/// </summary>
int id = -1;
public int ID
{
get
{
return id;
}
set
{
id = value;
}
}
/// <summary>
/// 连接状态
/// </summary>
bool connected = false;
public bool Connected
{
get
{
return connected;
}
set
{
connected = value;
if (connected == true)
{
adm.Start();
if (status.Status != JhThreadStatus.Running)
{
status.Status = JhThreadStatus.Running;
readThread = new Thread(new ThreadStart(this.DataReadThread));
readThread.Name = "Data reader of JH tcp client " + ID.ToString();
readThread.Start();
Console.WriteLine("Data reader of JH tcp client {0} started",ID);
LastReceivedTime = DateTime.Now;
if (ConnectCheck == true)
{
SendMessage(JhCommMessages.ConnectCheck,(Int32)CheckTimeout.Ticks);
StartConnectCheckThread();
}
}
}
else
{
status.Status = JhThreadStatus.Stop;
if (OnClosed != null) OnClosed(this,new CommEventArgs("连接已经断开!"));
}
}
}
/// <summary>
/// 尝试连接次数
/// </summary>
int connectTimes = 0;
/// <summary>
/// 读取数据线程
/// </summary>
Thread readThread = null;
/// <summary>
/// 自动断线重连标志
/// </summary>
bool autoConnect = false;
/// <summary>
/// 自动断线重连标志
/// </summary>
public bool AutoConnect
{
get
{
return autoConnect;
}
set
{
autoConnect = value;
if (autoConnect != true)
{
lock(this)
{
autoConnectStatus.Status = JhThreadStatus.Stop;
}
}
}
}
/// <summary>
/// 自动连接间隔毫秒数
/// </summary>
int autoConnectInterval = 3000;
/// <summary>
/// 自动连接间隔毫秒数
/// </summary>
public int AutoConnectInterval
{
get
{
return autoConnectInterval;
}
set
{
autoConnectInterval = value;
}
}
/// <summary>
/// 连接检测的状态控制
/// </summary>
Parm checkStatus = null;
/// <summary>
/// 自动连接的状态控制
/// </summary>
Parm autoConnectStatus = null;
/// <summary>
/// 连接监测标志
/// </summary>
bool connectCheck = false;
/// <summary>
/// 连接监测标志
/// </summary>
public bool ConnectCheck
{
get
{
return connectCheck;
}
set
{
bool b = value;
if (connectCheck != b)
{
if (connectCheck != true)//启动检测
{
lock(this)
{
checkStatus.Status = JhThreadStatus.Stop;
}
if (Connected == true)
{
SendMessage(JhCommMessages.StopCheck);
}
}
else
{
if (Connected == true) StartConnectCheckThread();
}
}
}
}
/// <summary>
/// 启动连接检测线程
/// </summary>
void StartConnectCheckThread()
{
if (checkStatus.Status != JhThreadStatus.Running)
{
checkStatus.Status = JhThreadStatus.Running;
Thread t = new Thread(new ThreadStart(ConnectCheckThread));
t.Name = "JH tcp client connecting checker of JH tcp client " + this.ID.ToString();
t.Start();
Console.WriteLine(t.Name + " started.");
}
}
/// <summary>
/// 连接关闭事件响应
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public virtual void OnConnectClosed(object sender,CommEventArgs e)
{
if (AutoConnect == true)//是否自动重连
{
StartAutoConnectThread();
}
}
/// <summary>
/// 启动自动重连线程
/// </summary>
void StartAutoConnectThread()
{
if (autoConnectStatus.Status != JhThreadStatus.Running)
{
connectTimes = 0;
autoConnectStatus.Status = JhThreadStatus.Running;
Thread t = new Thread(new ThreadStart(AutoConnectThread));
t.Name = "JH tcp client auto-connector of JH tcp client " + this.ID.ToString();
t.Start();
Console.WriteLine(t.Name + " started.");
}
}
/// <summary>
/// 最近一次通讯时间
/// </summary>
DateTime lastReceivedTime = DateTime.Now;
/// <summary>
/// 最近一次通讯时间
/// </summary>
public DateTime LastReceivedTime
{
get
{
return lastReceivedTime;
}
set
{
lastReceivedTime = value;
}
}
/// <summary>
/// 连接检测断开判断的最大允许毫秒数
/// </summary>
TimeSpan checkTimeout = new TimeSpan(1800000000);//3 minutes
/// <summary>
/// 连接检测断开判断的最大允许毫秒数
/// </summary>
public TimeSpan CheckTimeout
{
get
{
return checkTimeout;
}
set
{
TimeSpan ts = value;
if (ts.Minutes > 2) checkTimeout = ts;//检查时间间隔不小于2分钟
}
}
/// <summary>
/// 自动连接线程
/// </summary>
void AutoConnectThread()
{
try
{
while (autoConnectStatus.Status == JhThreadStatus.Running && AutoConnect == true)
{
if (Connected != true)
{
DoConnect();
Thread.Sleep(AutoConnectInterval);
}
else
{
break;
}
}
}
catch (Exception e3)
{
MessageBox.Show(e3.Message);
}
finally
{
lock (this)
{
autoConnectStatus.Status = JhThreadStatus.Exit;
}
}
}
/// <summary>
/// 连接检测线程
/// </summary>
void ConnectCheckThread()
{
try
{
while (checkStatus.Status == JhThreadStatus.Running)
{
if (Connected == true)
{
TimeSpan ts = DateTime.Now - lastReceivedTime;
TimeSpan ts2 = CheckTimeout + CheckTimeout;
if (ts > ts2 )//超过两倍间隔时间,认为已经断开
{
Close();
break;
}
else
{
SendMessage(JhCommMessages.ConnectSignal,(Int32)CheckTimeout.Ticks);
}
}
else
{
LastReceivedTime = DateTime.Now;
break;
}
Thread.Sleep(checkTimeout);
}
}
catch (Exception e3)
{
MessageBox.Show(e3.Message);
}
finally
{
lock(this)
{
checkStatus.Status = JhThreadStatus.Exit;
}
Console.WriteLine("JH tcp client connecting checker of JH tcp client " + this.ID.ToString() + " exited.") ;
}
}
/// <summary>
/// 读取数据的线程
/// </summary>
void DataReadThread()
{
try
{
while (status.Status == JhThreadStatus.Running)
{
if (Connected == true)
{
NetworkStream ns = Client.GetStream();
int readCount,totalRead = 0;
while (ns.DataAvailable == true)//读取数据,转存到s中,因为NetworkStream的数据只能向前读取一次
{
readCount = ns.Read(buffer, 0, bufferSize);
if (readCount > 0)
{
buf.Write(buffer, 0, readCount);
totalRead += readCount;
}
else
{
break;
}
} ;
if (totalRead > 0)//有数据
{
DealData();//处理
}
}
Thread.Sleep(50);
}
}
catch(IOException e3)
{
MessageBox.Show(e3.Message);
}
catch (ObjectDisposedException e2)
{
MessageBox.Show(e2.Message);
}
catch (InvalidOperationException e1)
{
MessageBox.Show(e1.Message);
}
catch (Exception e3)
{
MessageBox.Show(e3.Message);
}
finally
{
lock(this)
{
status.Status = JhThreadStatus.Exit;
}
Console.WriteLine("Data reader thread of JH tcp client {0} exited.",ID);
}
}
/// <summary>
/// 服务器ip
/// </summary>
string ipString;
/// <summary>
/// 服务器端口
/// </summary>
int tcpPort;
/// <summary>
/// 根据当前设置的ip和 port参数进行连接
/// </summary>
void DoConnect()
{
try
{
if (Connected == false)
{
if (Client == null)
{
Client = new TcpClient();
}
++ connectTimes ;
Client.Connect(ipString,tcpPort);
Connected = true;
autoConnectStatus.Status = JhThreadStatus.Stop;
if (OnConnected != null) OnConnected(this,new CommEventArgs("已经与服务器建立连接!"));
}
}
catch(Exception le)
{
if (OnConnectFailed != null) OnConnectFailed(this,new CommEventArgs("第" + connectTimes.ToString() + "次与服务器建立连接失败!" + le.Message));
}
}
/// <summary>
/// 连接服务器
/// </summary>
/// <param name="ip"></param>
/// <param name="port"></param>
public void Connect(string ip,int port)
{
ipString = ip;
tcpPort = port;
if (this.AutoConnect == true)
{
StartAutoConnectThread();
}
else
{
DoConnect();
}
}
/// <summary>
/// 发送数据
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public void Send(string data)
{
Send( data, System.Text.Encoding.Default);
}
/// <summary>
/// 发送数据
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public void Send(string data, System.Text.Encoding encodingway)
{
byte[] dt = encodingway.GetBytes(data);
Send(dt);
}
/// <summary>
/// 发送数据
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public void Send(byte[] data)
{
if (Connected == true)
{
CommHead ch = new CommHead();
ch.WParam = (short)JhCommMessages.DataTransfer;
ch.Add(data);
client.GetStream().Write(ch.ToBytes(),0,ch.Length);
}
else
{
MessageBox.Show("尚未建立连接或者连接已经断开!");
}
}
/// <summary>
/// 关闭连接
/// </summary>
public void Close()
{
if (Connected == true)
{
SendMessage(JhCommMessages.Disconnected);
Connected = false;
adm.Stop();
Client.Close();
Client = null;
}
}
/// <summary>
/// 程序退出时调用,或者设置AutoConnect = false
/// </summary>
public void Exit()
{
AutoConnect = false;
ConnectCheck = false;
Close();
}
/// <summary>
/// TCP客户对象
/// </summary>
TcpClient client = null;
/// <summary>
/// TCP客户对象
/// </summary>
public TcpClient Client
{
get
{
return client;
}
set
{
client = value;
}
}
/// <summary>
/// 缓存未处理的数据
/// </summary>
MemoryStream buf = new MemoryStream();
/// <summary>
/// 读取接收到的数据的缓冲区的大小
/// </summary>
const int bufferSize = 1024;
/// <summary>
/// 读取接收到的数据的缓冲区
/// </summary>
byte[] buffer = new byte[bufferSize];
/// <summary>
/// 数据分发管理者
/// </summary>
CommDataMgr adm ;
/// <summary>
/// 数据分发管理者
/// </summary>
public CommDataMgr DataMgr
{
set
{
adm = value;
}
}
/// <summary>
/// 接收到的数据的处理
/// </summary>
private void DealData()
{
// if (buf.Length > 0) //有数据需要处理
{
CommHead chio = new CommHead(buf,(int)buf.Position);
if (chio.IsValid())
{
LastReceivedTime = DateTime.Now;
if (chio.DataLen > 0)//有效数据
{
adm.AddData(this,chio.GetData(),chio.DataLen);//可处理数据
}
else//纯内部消息
{
switch ((JhCommMessages)chio.WParam)
{
case JhCommMessages.Disconnected: //对方将要断开连接消息
Close();
break;
case JhCommMessages.ConnectCheck:
if (CheckTimeout.Ticks != chio.DWParam)
{
CheckTimeout = new TimeSpan(chio.DWParam);
}
ConnectCheck = true;
break;
case JhCommMessages.StopCheck:
ConnectCheck = false;
break;
case JhCommMessages.ConnectSignal:
if (CheckTimeout.Ticks != chio.DWParam)
{
CheckTimeout = new TimeSpan(chio.DWParam);
}
break;
default:
break;
}
}
buf.Position = 0;
chio.GetLeftData(ref buf);//剩下未处理完数据
}
}
}
/// <summary>
/// 不带参数的消息
/// </summary>
/// <param name="message"></param>
private void SendMessage(JhCommMessages message)
{
SendMessage(message,0);
}
/// <summary>
/// 带参数的消息
/// </summary>
/// <param name="message"></param>
private void SendMessage(JhCommMessages message,Int32 parm)
{
CommHead ch = new CommHead();
ch.WParam = (short)message;
ch.DWParam = parm;
Client.GetStream().Write(ch.ToBytes(),0,16);
}
}
/// <summary>
/// Tcp通信服务器类
/// </summary>
public class JhTcpServer
{
public JhTcpServer(int port)
{
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");//Dns.Resolve("localhost").AddressList[0];
server = new TcpListener(ipAddress,port);
adm = new CommDataMgr();
status = new Parm(this);
}
~JhTcpServer()
{
Stop();
}
/// <summary>
/// Tcp监听对象
/// </summary>
TcpListener server = null;
/// <summary>
/// 客户端序号
/// </summary>
int clientindex = 0;
/// <summary>
/// 开始监听
/// </summary>
public void Start()
{
clients.Clear();
clientindex = 99999999;
adm.Start();
server.Start();
status.Status = JhThreadStatus.Running;
listenThread = new Thread(new ThreadStart(this.ListenThread));
listenThread.Name = "JH tcp listenor";
listenThread.Start();
Console.WriteLine("JH tcp listenor started.");
}
/// <summary>
/// 监听线程
/// </summary>
Thread listenThread = null;
/// <summary>
/// 停止接受连接
/// </summary>
public void Stop()
{
int i;
for (i = 0; i < this.clients.Count; ++i)
{
StopClient(i);
}
adm.Stop();
if (status.Status == JhThreadStatus.Running)
{
lock(this)
{
status.Status = JhThreadStatus.Stop;
}
while (status.Status != JhThreadStatus.Exit)
{
Thread.Sleep(100);
}
}
server.Stop();
}
/// <summary>
/// 断开指定索引的客户
/// </summary>
/// <param name="index">客户端索引</param>
public void StopClient(int index)
{
GetClient(index).Exit();
}
/// <summary>
/// 发送数据
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public void Send(JhClient client,string data)
{
if (client != null)
{
byte[] dt = System.Text.Encoding.Default.GetBytes(data);
client.Send(dt);
}
}
/// <summary>
/// 用最后一个客户端发送数据
/// </summary>
/// <param name="data"></param>
public void Send(string data)
{
Send(GetClient(clients.Count - 1),data);
}
/// <summary>
/// 数据分发管理者
/// </summary>
CommDataMgr adm ;
Parm status = null;
/// <summary>
/// 客户连接线程
/// </summary>
void ListenThread()
{
try
{
while (status.Status == JhThreadStatus.Running)
{
if (server.Pending() == true)
{
TcpClient client = server.AcceptTcpClient();//侦听到连接后创建客户端
JhClient jhClient = new JhClient(adm,client);
jhClient.ID = clientindex--;
SetClient(jhClient);
jhClient.Connected = true;
}
Thread.Sleep(100);
}
}
catch (ObjectDisposedException e2)
{
MessageBox.Show(e2.Message);
}
catch (InvalidOperationException e1)
{
MessageBox.Show(e1.Message);
}
catch (Exception e3)
{
MessageBox.Show(e3.Message);
}
finally
{
lock(this)
{
status.Status = JhThreadStatus.Exit;
}
Console.WriteLine("JH tcp listenor exited");
}
}
/// <summary>
/// 添加观察者
/// </summary>
/// <param name="ob"></param>
public void AddOb(IObserver ob)
{
adm.Add(ob);
}
Hashtable clients = new Hashtable();
/// <summary>
/// 根据内部id获取客户端
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public JhClient GetClient(int id)
{
return (JhClient)clients[id];
}
/// <summary>
/// 设置客户端对象
/// </summary>
/// <param name="client"></param>
public void SetClient(JhClient client)
{
int i;
for (i = 0 ; i < clients.Count; ++i)
{
if (((JhClient)clients[i]).ID == client.ID)
{
break;
}
}
clients[i] = client;
}
}
/// <summary>
/// 通信头处理类
/// </summary>
class CommHead
{
Int16 wHeadSize;// 头结构长度
Int16 wFlag;//合法数据包特征字
Int16 wVer;// 用版本号表示标识符
Int16 wParm;// 参数一
Int32 dwParm;// 参数二
Int32 dwDataLen;// 后续数据长度
/// <summary>
/// 新建头构造方法
/// </summary>
public CommHead() : this(System.Text.Encoding.Default)
{
Init();
}
/// <summary>
/// 新建头构造方法
/// </summary>
public CommHead(System.Text.Encoding enCoding)
{
encoding = enCoding;
Init();
}
System.Text.Encoding encoding;
/// <summary>
/// 解析数据构造方法
/// </summary>
/// <param name="s">数据流</param>
public CommHead(MemoryStream s,int len) : this(s,len,System.Text.Encoding.Default)
{
}
/// <summary>
/// 解析数据构造方法
/// </summary>
/// <param name="s">数据流</param>
/// <param name="encoding">字符编码方案</param>
public CommHead(MemoryStream s,int len,System.Text.Encoding encoding)
{
Init();
if (s != null)
{
s.Position = 0;
BinaryReader r = new BinaryReader(s,encoding);
wHeadSize = r.ReadInt16();
if (len >= wHeadSize)
{
wFlag = r.ReadInt16();
if (IsValid())
{
wVer = r.ReadInt16();
wParm = r.ReadInt16();
dwParm = r.ReadInt32();
dwDataLen = r.ReadInt32();
if (dwDataLen > 0)
{
byte[] dt = r.ReadBytes(dwDataLen);
if (dt != null) recvData = new MemoryStream(dt);
else
{
recvData = null;
dwDataLen = 0;
}
}
if (len > wHeadSize + dwDataLen)
{
byte[] dt = r.ReadBytes(len - wHeadSize - dwDataLen);
if (dt != null) moreData = new MemoryStream(dt);
else moreData = null;
}
}
}
}
}
MemoryStream recvData;
MemoryStream moreData;
void Init() {wFlag = 0x4a48; wVer = 1; wHeadSize = 16; }
// 当前头数据是否有效
public bool IsValid() {return wFlag == 0x4a48 && wHeadSize == 16; }
// 返回双字节参数
public Int32 DWParam
{
get
{
return dwParm;
}
set
{
dwParm = value;
}
}
// 返回单字节参数
public Int16 WParam
{
get
{
return wParm;
}
set
{
wParm = value;
}
}
// 返回头结构大小
public Int16 HeadSize
{
get
{
return wHeadSize;
}
}
// 返回版本标识符
public virtual Int16 Ver
{
get
{
return wVer;
}
}
// 返回后续数据长度
public virtual Int32 DataLen
{
get
{
return dwDataLen;
}
set
{
dwDataLen = value;
}
}
/// <summary>
/// 返回未处理数据
/// </summary>
/// <returns></returns>
public void GetLeftData(ref MemoryStream s)
{
if (moreData != null)
{
moreData.WriteTo(s);
moreData.Close();
}
}
/// <summary>
/// 返回完整数据
/// </summary>
/// <returns></returns>
public MemoryStream GetData()
{
return recvData;
}
/// <summary>
/// 添加数据
/// </summary>
/// <param name="pszData"></param>
public void Add(byte[] pszData)
{
data.Write(pszData,0,pszData.Length);
dwDataLen += pszData.Length;
}
MemoryStream data = new MemoryStream();
/// <summary>
/// 需要发送的数据转为字节数组
/// </summary>
/// <returns></returns>
public byte[] ToBytes()
{
MemoryStream s = new MemoryStream();
BinaryWriter w = new BinaryWriter(s,encoding);
w.Write(wHeadSize);
w.Write(wFlag);
w.Write(wVer);
w.Write(wParm);
w.Write(dwParm);
w.Write(dwDataLen);
// w.Close();
data.WriteTo(s);
return s.ToArray();
}
/// <summary>
/// 需要发送的数据的长度
/// </summary>
public int Length
{
get
{
return (int)data.Length + wHeadSize;
}
}
}
}
namespace Jh.Sockets
{
/// <summary>
/// 字符串特性常量存放类
/// </summary>
public class JhStringConst
{
public const int SHORT_STRING_LEN = 16;
public const int NORMAL_STRING_LEN = 32;
public const int MIDD_STRING_LEN = 64;
public const int LONG_STRING_LEN = 128;
public const int LONGER_STRING_LEN = 256;
public const int EXLONG_STRING_LEN = 1024;
}
}
namespace Jh.Sockets
{
/// <summary>
/// 线程状态信号定义
/// </summary>
public enum JhThreadStatus
{
Stop, //停止
Running, //正在运行
Exit //已退出
}
/// <summary>
/// 线程状态参数
/// </summary>
class Parm
{
public Parm(object obj):this(JhThreadStatus.Stop,obj)
{
}
public Parm(JhThreadStatus nStatus,object obj)
{
Status = nStatus;
ObjParm = obj;
}
JhThreadStatus status;
object objParm;
/// <summary>
/// 上下文对象
/// </summary>
public object ObjParm
{
get
{
return objParm;
}
set
{
objParm = value;
}
}
/// <summary>
/// 控制状态
/// </summary>
public JhThreadStatus Status
{
get
{
return status;
}
set
{
status = value;
}
}
};
/// <summary>
/// 通讯数据处理接口
/// </summary>
public interface IObserver
{
//
// 数据处理入口
//
void Deal(CommData cd);
//
// 数据处理重载方法.如果不希望后面的处理者继续处理数据,则返回true,否则返回false;
//
bool OnDeal(CommData cd);
//
// 附加的自身初始化操作
//
bool Init();
//
// 提前初始化接口
//
bool BeforeInit();
//
// 初始化后处理接口
//
bool AfterInit();
//
// 删除前处理接口
//
bool BeforeExit();
//
// 下一个观察者
//
IObserver Next
{
get;
set;
}
//
// 上一个观察者
//
IObserver Prev
{
get;
set;
}
//
// 添加观察者到后面,如果已经存在链表中则不做任何操作
//
void Add(IObserver observer);
//
// 插入观察者到下一个观察者的前面
//
void Insert(IObserver observer);
//删除观察者
void Remove(IObserver observer);
//是否存在链表中
bool IsExist(IObserver observer);
}
/// <summary>
/// 通讯数据处理类的基类,只能派生
/// </summary>
public abstract class Observer : IObserver
{
/// <summary>
/// 数据处理入口.
/// </summary>
/// <param name="client">TcpClient类 实例</param>
/// <param name="s">内存数据流</param>
public void Deal(CommData cd)
{
cd.Data.Position = 0;
if (OnDeal(cd) == false) return ;
if (next != null)
{
next.Deal(cd);
}
return ;
}
/// <summary>
/// 数据处理重载方法.
/// </summary>
/// <param name="client">TcpClient类 实例</param>
/// <param name="s">内存数据流</param>
/// <returns>处理结果,如果不希望后面的处理者继续处理数据,则返回false,否则返回true;</returns>
public virtual bool OnDeal(CommData cd)
{
return true;
}
//附加的自身初始化操作
public virtual bool Init()
{
return true;
}
//提前初始化接口
public virtual bool BeforeInit()
{
return true;
}
//初始化后处理接口
public virtual bool AfterInit()
{
return true;
}
//删除前处理接口
public virtual bool BeforeExit()
{
return true;
}
//下一个观察者
IObserver next = null;
public IObserver Next
{
get
{
return next;
}
set
{
next = value;
}
}
//上一个观察者
IObserver prev = null;
public IObserver Prev
{
get
{
return prev;
}
set
{
prev = value;
}
}
//添加观察者
public void Add(IObserver observer)
{
if (this == observer) return;//已经存在
if (next == null)
{
next = observer;//达到最底端
next.Prev = this;
}
else next.Add(observer);//加到后面
}
/// <summary>
/// 插入观察者到下一个观察者的前面
/// </summary>
/// <param name="observer"></param>
public void Insert(IObserver observer)
{
//是否等于自己
if (this == observer) return;
//先查找是否已经存在链表中
if (Next != null && Next.IsExist(observer)) Next.Remove(observer);
//
observer.Next = Next;
if (Next != null) Next.Prev = observer;
Next = observer;
observer.Prev = this;
}
/// <summary>
/// 删除观察者
/// </summary>
/// <param name="observer"></param>
public void Remove(IObserver observer)
{
if (observer == this)
{
if (Prev != null) Prev.Next = Next;
if (Next != null) Next.Prev = Prev;
}
else
{
if (Next != null) Next.Remove(observer);
}
}
/// <summary>
/// 查找是否存在
/// </summary>
/// <param name="observer"></param>
/// <returns></returns>
public bool IsExist(IObserver observer)
{
if (observer == this) return true;
if (Next == null) return false;
else return Next.IsExist(observer);
}
}
/// <summary>
/// 日志处理基类,本身从通讯数据处理类的基类派生。
/// </summary>
class Log : Observer
{
public Log()
{
}
public Log(string slogfile)
{
LogFile = slogfile;
}
~Log()
{
}
// 日志文件带路径名称
private string logFile;
public string LogFile
{
get
{
return logFile;
}
set
{
logFile = value;
}
}
}
}
using System;
using System.Collections;
using System.IO;
using System.Threading;
namespace Jh.Sockets
{
/// <summary>
/// 数据集中管理类
/// </summary>
public class CommDataMgr
{
static int index = 0;
int id;
/// <summary>
/// 无参数构造方法
/// </summary>
public CommDataMgr()
{
id = index ++;
dnFlag = new Parm(this);
Console.WriteLine("JH data distributor {0} constructed",id);
}
Thread t = null;
public void Start()
{
if (dnFlag.Status != JhThreadStatus.Running)
{
dnFlag.Status = JhThreadStatus.Running;
t = new Thread (new ThreadStart(DataNotiyfyThread));
t.Name = "JH data distributing " + id.ToString();
t.Start();
Console.WriteLine("JH data distributing thread of JH data distributor {0} started",id);
}
}
public void Stop()
{
if ( dnFlag.Status == JhThreadStatus.Running )
{
lock (this)
{
dnFlag.Status = JhThreadStatus.Stop;
}
}
}
/// <summary>
/// 析构方法
/// </summary>
~CommDataMgr()
{
Stop();
Console.WriteLine("JH data distributor {0} unconstructed",id);
}
public void DataNotiyfyThread()
{
try
{
while (dnFlag.Status == JhThreadStatus.Running)
{
DealData();
Thread.Sleep(100);
// Console.WriteLine("分发线程{0}工作中",id);
}
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
finally
{
lock(this)
{
dnFlag.Status = JhThreadStatus.Exit;
}
Console.WriteLine("JH data distributing thread of JH data distributor {0} exited",id);
}
}
Parm dnFlag = null;
ArrayList aData = new ArrayList();
InnerObserver root = new InnerObserver();
/// <summary>
/// 观察者根节点类 定义
/// </summary>
internal class InnerObserver : Observer
{
}
public void DealData()
{
if (DataCount > 0)
{
lock(this)
{
if (root.Next != null)
{
root.Next.Deal((CommData)aData[0]);
}
RemoveAt(0);
}
}
}
/// <summary>
/// 未处理数据个数
/// </summary>
public int DataCount
{
get
{
return aData.Count;
}
}
/// <summary>
/// 根据索引返回未处理数据
/// </summary>
internal CommData this[int Index]
{
get
{
return (CommData)aData[Index];
}
}
/// <summary>
/// 根据索引删除数据
/// </summary>
/// <param name="Index">索引</param>
public void RemoveAt(int Index)
{
if (Index >= 0 && Index < DataCount)
{
lock (this)
{
aData.RemoveAt(Index);
}
}
}
/// <summary>
/// 接收到新的数据提交
/// </summary>
/// <param name="client">客户端连接</param>
/// <param name="s">数据流</param>
public void AddData(JhClient client,MemoryStream s,int len)
{
CommData cd = new CommData(client,s,len,this);
lock(this)
{
aData.Add(cd);
}
}
/// <summary>
/// 添加观察者
/// </summary>
/// <param name="observer"></param>
public void Add(IObserver observer)
{
lock (this)
{
root.Add(observer);
}
}
/// <summary>
/// 删除观察者
/// </summary>
/// <param name="observer"></param>
public void Remove(IObserver observer)
{
lock (this)
{
root.Remove(observer);
}
}
/// <summary>
/// 在最前面插入观察者
/// </summary>
/// <param name="observer"></param>
public void Insert(IObserver observer)
{
lock (this)
{
root.Insert(observer);
}
}
// 取观察者个数
// int GetObserverCount()
// {
// return (int)m_aObservers.GetCount();
// }
}
}
using System;
using System.Threading;
using System.Net.Sockets;
using System.IO;
using System.Collections;
using System.Windows.Forms;
using System.Net;
namespace Jh.Sockets
{
/// <summary>
/// 内部通信消息
/// </summary>
enum JhCommMessages
{
MessageStart = 9909,//消息起始
DataTransfer, //数据传输
Disconnected, //连接将要断开
ConnectSignal, //连接检查信号
ConnectCheck, //启动连接信号
StopCheck, //停止连接信号
Unknown = 9999 //未知
}
/// <summary>
/// 通信数据
/// </summary>
public class CommData
{
public CommData(JhClient client,MemoryStream stream,int len,CommDataMgr dm)
{
jhClient = client;
Data = new MemoryStream();
stream.WriteTo(Data);
dataLen = len;
adm = dm;
}
JhClient jhClient;
MemoryStream data;
int dataLen;
CommDataMgr adm;
/// <summary>
/// tcp连接
/// </summary>
public JhClient Socket
{
get
{
return jhClient;
}
}
/// <summary>
/// 内存数据流
/// </summary>
public MemoryStream Data
{
get
{
return data;
}
set
{
data = value;
}
}
/// <summary>
/// 数据长度
/// </summary>
public int DataLen
{
get
{
return dataLen;
}
}
};
public delegate void CommEventHandler(object sender,CommEventArgs e);
public class CommEventArgs : EventArgs
{
public CommEventArgs(string msg):base()
{
Message = msg;
}
string message;
public string Message
{
get
{
return message;
}
set
{
message = value;
}
}
}
/// <summary>
/// Tcp通信客户类
/// </summary>
public class JhClient
{
/// <summary>
/// 连接成功事件
/// </summary>
public event CommEventHandler OnConnected;
/// <summary>
/// 连接关闭事件
/// </summary>
public event CommEventHandler OnClosed;
/// <summary>
/// 连接失败事件
/// </summary>
public event CommEventHandler OnConnectFailed;
/// <summary>
/// 构造方法
/// </summary>
/// <param name="dm">外部植入的数据管理类</param>
/// <param name="ob">观察者</param>
/// <param name="tcpClient">通信连接</param>
public JhClient(CommDataMgr dm,IObserver ob,TcpClient tcpClient)
{
//
// TODO: 在此处添加构造函数逻辑
//
status = new Parm(this);
checkStatus = new Parm(this);
autoConnectStatus = new Parm(this);
if (dm == null)
{
adm = new CommDataMgr();
}
else adm = dm;
if (ob != null) adm.Add(ob);
if (tcpClient == null)
{
client = new TcpClient();
}
else client = tcpClient;
ID = index ++;
OnClosed += new CommEventHandler(OnConnectClosed);
Console.WriteLine("JH tcp client {0} constructed",ID);
}
static int index = 0;
/// <summary>
/// 无参数构造函数
/// </summary>
public JhClient(TcpClient tcpClient) : this(null,null,tcpClient)
{}
public JhClient(CommDataMgr dm,TcpClient tcpClient) : this(dm,null,tcpClient)
{}
public JhClient(IObserver ob,TcpClient tcpClient):this(null,ob,tcpClient)
{}
public JhClient() : this(null,null,null)
{}
public JhClient(CommDataMgr dm) : this(dm,null,null)
{}
public JhClient(IObserver ob):this(null,ob,null)
{}
/// <summary>
/// 析构方法
/// </summary>
~JhClient()
{
AutoConnect = false;
ConnectCheck = false;
Close();
Console.WriteLine("JH tcp client {0} unconstructed",ID);
}
Parm status = null;
/// <summary>
/// 唯一标志符
/// </summary>
int id = -1;
public int ID
{
get
{
return id;
}
set
{
id = value;
}
}
/// <summary>
/// 连接状态
/// </summary>
bool connected = false;
public bool Connected
{
get
{
return connected;
}
set
{
connected = value;
if (connected == true)
{
adm.Start();
if (status.Status != JhThreadStatus.Running)
{
status.Status = JhThreadStatus.Running;
readThread = new Thread(new ThreadStart(this.DataReadThread));
readThread.Name = "Data reader of JH tcp client " + ID.ToString();
readThread.Start();
Console.WriteLine("Data reader of JH tcp client {0} started",ID);
LastReceivedTime = DateTime.Now;
if (ConnectCheck == true)
{
SendMessage(JhCommMessages.ConnectCheck,(Int32)CheckTimeout.Ticks);
StartConnectCheckThread();
}
}
}
else
{
status.Status = JhThreadStatus.Stop;
if (OnClosed != null) OnClosed(this,new CommEventArgs("连接已经断开!"));
}
}
}
/// <summary>
/// 尝试连接次数
/// </summary>
int connectTimes = 0;
/// <summary>
/// 读取数据线程
/// </summary>
Thread readThread = null;
/// <summary>
/// 自动断线重连标志
/// </summary>
bool autoConnect = false;
/// <summary>
/// 自动断线重连标志
/// </summary>
public bool AutoConnect
{
get
{
return autoConnect;
}
set
{
autoConnect = value;
if (autoConnect != true)
{
lock(this)
{
autoConnectStatus.Status = JhThreadStatus.Stop;
}
}
}
}
/// <summary>
/// 自动连接间隔毫秒数
/// </summary>
int autoConnectInterval = 3000;
/// <summary>
/// 自动连接间隔毫秒数
/// </summary>
public int AutoConnectInterval
{
get
{
return autoConnectInterval;
}
set
{
autoConnectInterval = value;
}
}
/// <summary>
/// 连接检测的状态控制
/// </summary>
Parm checkStatus = null;
/// <summary>
/// 自动连接的状态控制
/// </summary>
Parm autoConnectStatus = null;
/// <summary>
/// 连接监测标志
/// </summary>
bool connectCheck = false;
/// <summary>
/// 连接监测标志
/// </summary>
public bool ConnectCheck
{
get
{
return connectCheck;
}
set
{
bool b = value;
if (connectCheck != b)
{
if (connectCheck != true)//启动检测
{
lock(this)
{
checkStatus.Status = JhThreadStatus.Stop;
}
if (Connected == true)
{
SendMessage(JhCommMessages.StopCheck);
}
}
else
{
if (Connected == true) StartConnectCheckThread();
}
}
}
}
/// <summary>
/// 启动连接检测线程
/// </summary>
void StartConnectCheckThread()
{
if (checkStatus.Status != JhThreadStatus.Running)
{
checkStatus.Status = JhThreadStatus.Running;
Thread t = new Thread(new ThreadStart(ConnectCheckThread));
t.Name = "JH tcp client connecting checker of JH tcp client " + this.ID.ToString();
t.Start();
Console.WriteLine(t.Name + " started.");
}
}
/// <summary>
/// 连接关闭事件响应
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public virtual void OnConnectClosed(object sender,CommEventArgs e)
{
if (AutoConnect == true)//是否自动重连
{
StartAutoConnectThread();
}
}
/// <summary>
/// 启动自动重连线程
/// </summary>
void StartAutoConnectThread()
{
if (autoConnectStatus.Status != JhThreadStatus.Running)
{
connectTimes = 0;
autoConnectStatus.Status = JhThreadStatus.Running;
Thread t = new Thread(new ThreadStart(AutoConnectThread));
t.Name = "JH tcp client auto-connector of JH tcp client " + this.ID.ToString();
t.Start();
Console.WriteLine(t.Name + " started.");
}
}
/// <summary>
/// 最近一次通讯时间
/// </summary>
DateTime lastReceivedTime = DateTime.Now;
/// <summary>
/// 最近一次通讯时间
/// </summary>
public DateTime LastReceivedTime
{
get
{
return lastReceivedTime;
}
set
{
lastReceivedTime = value;
}
}
/// <summary>
/// 连接检测断开判断的最大允许毫秒数
/// </summary>
TimeSpan checkTimeout = new TimeSpan(1800000000);//3 minutes
/// <summary>
/// 连接检测断开判断的最大允许毫秒数
/// </summary>
public TimeSpan CheckTimeout
{
get
{
return checkTimeout;
}
set
{
TimeSpan ts = value;
if (ts.Minutes > 2) checkTimeout = ts;//检查时间间隔不小于2分钟
}
}
/// <summary>
/// 自动连接线程
/// </summary>
void AutoConnectThread()
{
try
{
while (autoConnectStatus.Status == JhThreadStatus.Running && AutoConnect == true)
{
if (Connected != true)
{
DoConnect();
Thread.Sleep(AutoConnectInterval);
}
else
{
break;
}
}
}
catch (Exception e3)
{
MessageBox.Show(e3.Message);
}
finally
{
lock (this)
{
autoConnectStatus.Status = JhThreadStatus.Exit;
}
}
}
/// <summary>
/// 连接检测线程
/// </summary>
void ConnectCheckThread()
{
try
{
while (checkStatus.Status == JhThreadStatus.Running)
{
if (Connected == true)
{
TimeSpan ts = DateTime.Now - lastReceivedTime;
TimeSpan ts2 = CheckTimeout + CheckTimeout;
if (ts > ts2 )//超过两倍间隔时间,认为已经断开
{
Close();
break;
}
else
{
SendMessage(JhCommMessages.ConnectSignal,(Int32)CheckTimeout.Ticks);
}
}
else
{
LastReceivedTime = DateTime.Now;
break;
}
Thread.Sleep(checkTimeout);
}
}
catch (Exception e3)
{
MessageBox.Show(e3.Message);
}
finally
{
lock(this)
{
checkStatus.Status = JhThreadStatus.Exit;
}
Console.WriteLine("JH tcp client connecting checker of JH tcp client " + this.ID.ToString() + " exited.") ;
}
}
/// <summary>
/// 读取数据的线程
/// </summary>
void DataReadThread()
{
try
{
while (status.Status == JhThreadStatus.Running)
{
if (Connected == true)
{
NetworkStream ns = Client.GetStream();
int readCount,totalRead = 0;
while (ns.DataAvailable == true)//读取数据,转存到s中,因为NetworkStream的数据只能向前读取一次
{
readCount = ns.Read(buffer, 0, bufferSize);
if (readCount > 0)
{
buf.Write(buffer, 0, readCount);
totalRead += readCount;
}
else
{
break;
}
} ;
if (totalRead > 0)//有数据
{
DealData();//处理
}
}
Thread.Sleep(50);
}
}
catch(IOException e3)
{
MessageBox.Show(e3.Message);
}
catch (ObjectDisposedException e2)
{
MessageBox.Show(e2.Message);
}
catch (InvalidOperationException e1)
{
MessageBox.Show(e1.Message);
}
catch (Exception e3)
{
MessageBox.Show(e3.Message);
}
finally
{
lock(this)
{
status.Status = JhThreadStatus.Exit;
}
Console.WriteLine("Data reader thread of JH tcp client {0} exited.",ID);
}
}
/// <summary>
/// 服务器ip
/// </summary>
string ipString;
/// <summary>
/// 服务器端口
/// </summary>
int tcpPort;
/// <summary>
/// 根据当前设置的ip和 port参数进行连接
/// </summary>
void DoConnect()
{
try
{
if (Connected == false)
{
if (Client == null)
{
Client = new TcpClient();
}
++ connectTimes ;
Client.Connect(ipString,tcpPort);
Connected = true;
autoConnectStatus.Status = JhThreadStatus.Stop;
if (OnConnected != null) OnConnected(this,new CommEventArgs("已经与服务器建立连接!"));
}
}
catch(Exception le)
{
if (OnConnectFailed != null) OnConnectFailed(this,new CommEventArgs("第" + connectTimes.ToString() + "次与服务器建立连接失败!" + le.Message));
}
}
/// <summary>
/// 连接服务器
/// </summary>
/// <param name="ip"></param>
/// <param name="port"></param>
public void Connect(string ip,int port)
{
ipString = ip;
tcpPort = port;
if (this.AutoConnect == true)
{
StartAutoConnectThread();
}
else
{
DoConnect();
}
}
/// <summary>
/// 发送数据
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public void Send(string data)
{
Send( data, System.Text.Encoding.Default);
}
/// <summary>
/// 发送数据
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public void Send(string data, System.Text.Encoding encodingway)
{
byte[] dt = encodingway.GetBytes(data);
Send(dt);
}
/// <summary>
/// 发送数据
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public void Send(byte[] data)
{
if (Connected == true)
{
CommHead ch = new CommHead();
ch.WParam = (short)JhCommMessages.DataTransfer;
ch.Add(data);
client.GetStream().Write(ch.ToBytes(),0,ch.Length);
}
else
{
MessageBox.Show("尚未建立连接或者连接已经断开!");
}
}
/// <summary>
/// 关闭连接
/// </summary>
public void Close()
{
if (Connected == true)
{
SendMessage(JhCommMessages.Disconnected);
Connected = false;
adm.Stop();
Client.Close();
Client = null;
}
}
/// <summary>
/// 程序退出时调用,或者设置AutoConnect = false
/// </summary>
public void Exit()
{
AutoConnect = false;
ConnectCheck = false;
Close();
}
/// <summary>
/// TCP客户对象
/// </summary>
TcpClient client = null;
/// <summary>
/// TCP客户对象
/// </summary>
public TcpClient Client
{
get
{
return client;
}
set
{
client = value;
}
}
/// <summary>
/// 缓存未处理的数据
/// </summary>
MemoryStream buf = new MemoryStream();
/// <summary>
/// 读取接收到的数据的缓冲区的大小
/// </summary>
const int bufferSize = 1024;
/// <summary>
/// 读取接收到的数据的缓冲区
/// </summary>
byte[] buffer = new byte[bufferSize];
/// <summary>
/// 数据分发管理者
/// </summary>
CommDataMgr adm ;
/// <summary>
/// 数据分发管理者
/// </summary>
public CommDataMgr DataMgr
{
set
{
adm = value;
}
}
/// <summary>
/// 接收到的数据的处理
/// </summary>
private void DealData()
{
// if (buf.Length > 0) //有数据需要处理
{
CommHead chio = new CommHead(buf,(int)buf.Position);
if (chio.IsValid())
{
LastReceivedTime = DateTime.Now;
if (chio.DataLen > 0)//有效数据
{
adm.AddData(this,chio.GetData(),chio.DataLen);//可处理数据
}
else//纯内部消息
{
switch ((JhCommMessages)chio.WParam)
{
case JhCommMessages.Disconnected: //对方将要断开连接消息
Close();
break;
case JhCommMessages.ConnectCheck:
if (CheckTimeout.Ticks != chio.DWParam)
{
CheckTimeout = new TimeSpan(chio.DWParam);
}
ConnectCheck = true;
break;
case JhCommMessages.StopCheck:
ConnectCheck = false;
break;
case JhCommMessages.ConnectSignal:
if (CheckTimeout.Ticks != chio.DWParam)
{
CheckTimeout = new TimeSpan(chio.DWParam);
}
break;
default:
break;
}
}
buf.Position = 0;
chio.GetLeftData(ref buf);//剩下未处理完数据
}
}
}
/// <summary>
/// 不带参数的消息
/// </summary>
/// <param name="message"></param>
private void SendMessage(JhCommMessages message)
{
SendMessage(message,0);
}
/// <summary>
/// 带参数的消息
/// </summary>
/// <param name="message"></param>
private void SendMessage(JhCommMessages message,Int32 parm)
{
CommHead ch = new CommHead();
ch.WParam = (short)message;
ch.DWParam = parm;
Client.GetStream().Write(ch.ToBytes(),0,16);
}
}
/// <summary>
/// Tcp通信服务器类
/// </summary>
public class JhTcpServer
{
public JhTcpServer(int port)
{
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");//Dns.Resolve("localhost").AddressList[0];
server = new TcpListener(ipAddress,port);
adm = new CommDataMgr();
status = new Parm(this);
}
~JhTcpServer()
{
Stop();
}
/// <summary>
/// Tcp监听对象
/// </summary>
TcpListener server = null;
/// <summary>
/// 客户端序号
/// </summary>
int clientindex = 0;
/// <summary>
/// 开始监听
/// </summary>
public void Start()
{
clients.Clear();
clientindex = 99999999;
adm.Start();
server.Start();
status.Status = JhThreadStatus.Running;
listenThread = new Thread(new ThreadStart(this.ListenThread));
listenThread.Name = "JH tcp listenor";
listenThread.Start();
Console.WriteLine("JH tcp listenor started.");
}
/// <summary>
/// 监听线程
/// </summary>
Thread listenThread = null;
/// <summary>
/// 停止接受连接
/// </summary>
public void Stop()
{
int i;
for (i = 0; i < this.clients.Count; ++i)
{
StopClient(i);
}
adm.Stop();
if (status.Status == JhThreadStatus.Running)
{
lock(this)
{
status.Status = JhThreadStatus.Stop;
}
while (status.Status != JhThreadStatus.Exit)
{
Thread.Sleep(100);
}
}
server.Stop();
}
/// <summary>
/// 断开指定索引的客户
/// </summary>
/// <param name="index">客户端索引</param>
public void StopClient(int index)
{
GetClient(index).Exit();
}
/// <summary>
/// 发送数据
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public void Send(JhClient client,string data)
{
if (client != null)
{
byte[] dt = System.Text.Encoding.Default.GetBytes(data);
client.Send(dt);
}
}
/// <summary>
/// 用最后一个客户端发送数据
/// </summary>
/// <param name="data"></param>
public void Send(string data)
{
Send(GetClient(clients.Count - 1),data);
}
/// <summary>
/// 数据分发管理者
/// </summary>
CommDataMgr adm ;
Parm status = null;
/// <summary>
/// 客户连接线程
/// </summary>
void ListenThread()
{
try
{
while (status.Status == JhThreadStatus.Running)
{
if (server.Pending() == true)
{
TcpClient client = server.AcceptTcpClient();//侦听到连接后创建客户端
JhClient jhClient = new JhClient(adm,client);
jhClient.ID = clientindex--;
SetClient(jhClient);
jhClient.Connected = true;
}
Thread.Sleep(100);
}
}
catch (ObjectDisposedException e2)
{
MessageBox.Show(e2.Message);
}
catch (InvalidOperationException e1)
{
MessageBox.Show(e1.Message);
}
catch (Exception e3)
{
MessageBox.Show(e3.Message);
}
finally
{
lock(this)
{
status.Status = JhThreadStatus.Exit;
}
Console.WriteLine("JH tcp listenor exited");
}
}
/// <summary>
/// 添加观察者
/// </summary>
/// <param name="ob"></param>
public void AddOb(IObserver ob)
{
adm.Add(ob);
}
Hashtable clients = new Hashtable();
/// <summary>
/// 根据内部id获取客户端
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public JhClient GetClient(int id)
{
return (JhClient)clients[id];
}
/// <summary>
/// 设置客户端对象
/// </summary>
/// <param name="client"></param>
public void SetClient(JhClient client)
{
int i;
for (i = 0 ; i < clients.Count; ++i)
{
if (((JhClient)clients[i]).ID == client.ID)
{
break;
}
}
clients[i] = client;
}
}
/// <summary>
/// 通信头处理类
/// </summary>
class CommHead
{
Int16 wHeadSize;// 头结构长度
Int16 wFlag;//合法数据包特征字
Int16 wVer;// 用版本号表示标识符
Int16 wParm;// 参数一
Int32 dwParm;// 参数二
Int32 dwDataLen;// 后续数据长度
/// <summary>
/// 新建头构造方法
/// </summary>
public CommHead() : this(System.Text.Encoding.Default)
{
Init();
}
/// <summary>
/// 新建头构造方法
/// </summary>
public CommHead(System.Text.Encoding enCoding)
{
encoding = enCoding;
Init();
}
System.Text.Encoding encoding;
/// <summary>
/// 解析数据构造方法
/// </summary>
/// <param name="s">数据流</param>
public CommHead(MemoryStream s,int len) : this(s,len,System.Text.Encoding.Default)
{
}
/// <summary>
/// 解析数据构造方法
/// </summary>
/// <param name="s">数据流</param>
/// <param name="encoding">字符编码方案</param>
public CommHead(MemoryStream s,int len,System.Text.Encoding encoding)
{
Init();
if (s != null)
{
s.Position = 0;
BinaryReader r = new BinaryReader(s,encoding);
wHeadSize = r.ReadInt16();
if (len >= wHeadSize)
{
wFlag = r.ReadInt16();
if (IsValid())
{
wVer = r.ReadInt16();
wParm = r.ReadInt16();
dwParm = r.ReadInt32();
dwDataLen = r.ReadInt32();
if (dwDataLen > 0)
{
byte[] dt = r.ReadBytes(dwDataLen);
if (dt != null) recvData = new MemoryStream(dt);
else
{
recvData = null;
dwDataLen = 0;
}
}
if (len > wHeadSize + dwDataLen)
{
byte[] dt = r.ReadBytes(len - wHeadSize - dwDataLen);
if (dt != null) moreData = new MemoryStream(dt);
else moreData = null;
}
}
}
}
}
MemoryStream recvData;
MemoryStream moreData;
void Init() {wFlag = 0x4a48; wVer = 1; wHeadSize = 16; }
// 当前头数据是否有效
public bool IsValid() {return wFlag == 0x4a48 && wHeadSize == 16; }
// 返回双字节参数
public Int32 DWParam
{
get
{
return dwParm;
}
set
{
dwParm = value;
}
}
// 返回单字节参数
public Int16 WParam
{
get
{
return wParm;
}
set
{
wParm = value;
}
}
// 返回头结构大小
public Int16 HeadSize
{
get
{
return wHeadSize;
}
}
// 返回版本标识符
public virtual Int16 Ver
{
get
{
return wVer;
}
}
// 返回后续数据长度
public virtual Int32 DataLen
{
get
{
return dwDataLen;
}
set
{
dwDataLen = value;
}
}
/// <summary>
/// 返回未处理数据
/// </summary>
/// <returns></returns>
public void GetLeftData(ref MemoryStream s)
{
if (moreData != null)
{
moreData.WriteTo(s);
moreData.Close();
}
}
/// <summary>
/// 返回完整数据
/// </summary>
/// <returns></returns>
public MemoryStream GetData()
{
return recvData;
}
/// <summary>
/// 添加数据
/// </summary>
/// <param name="pszData"></param>
public void Add(byte[] pszData)
{
data.Write(pszData,0,pszData.Length);
dwDataLen += pszData.Length;
}
MemoryStream data = new MemoryStream();
/// <summary>
/// 需要发送的数据转为字节数组
/// </summary>
/// <returns></returns>
public byte[] ToBytes()
{
MemoryStream s = new MemoryStream();
BinaryWriter w = new BinaryWriter(s,encoding);
w.Write(wHeadSize);
w.Write(wFlag);
w.Write(wVer);
w.Write(wParm);
w.Write(dwParm);
w.Write(dwDataLen);
// w.Close();
data.WriteTo(s);
return s.ToArray();
}
/// <summary>
/// 需要发送的数据的长度
/// </summary>
public int Length
{
get
{
return (int)data.Length + wHeadSize;
}
}
}
}
namespace Jh.Sockets
{
/// <summary>
/// 字符串特性常量存放类
/// </summary>
public class JhStringConst
{
public const int SHORT_STRING_LEN = 16;
public const int NORMAL_STRING_LEN = 32;
public const int MIDD_STRING_LEN = 64;
public const int LONG_STRING_LEN = 128;
public const int LONGER_STRING_LEN = 256;
public const int EXLONG_STRING_LEN = 1024;
}
}