最近做了一个Socket的DLL,主要实现的功能是给顶层仅提供数据包的接口。简化顶层程序在通讯方面的实现。
就是创建一个Client C1实例,必须使用给定的消息头格式,可以让C1发送数据包,从C1获取数据包。现在领导要求在其上包上一层,实现流量控制、窗口控制等功能,请大侠们指点一下,提供相关的参考书名。
就是创建一个Client C1实例,必须使用给定的消息头格式,可以让C1发送数据包,从C1获取数据包。现在领导要求在其上包上一层,实现流量控制、窗口控制等功能,请大侠们指点一下,提供相关的参考书名。
解决方案 »
- 大家帮我看看这个多线程问题!
- 如何在RichTextBox控件中插入文件内容
- datagridview的按下SHIFT或Ctrl键多选的功能怎么没有了?
- 如何在pictureBox上分区域?
- 关于C# mobile socket 的编程
- 求好心人提供form应用程序标准ico图标,网上找了半天没合适的。
- 怎样通过 XML 实现在两个不同类型的数据库之间复制表?
- 怎样学习C#语言和ASP.NET
- VB.NET中的shared,在c#中怎么实现呀???
- C#写的windows 服务程序怎么特耗资源?
- 如何程序取datagridview列的名称?
- 利用ContextMenuStrip控件,用同样的方法,在按钮上能弹出右键菜单,而在MSHFlexGrid控件中点击右键为什么弹不出右键菜单呢?
如果是供多个上层程序用,就不行了。
感觉你还是在上层直接记录的好。
在顶层程序控制和在DLL控制,如果数据量大于网络流量,都是要占电脑内存,
在DLL中占用好像也没多大问题,我想先实现出来再对比效果。
是提供多个的,部分源代码:
public class Client
{
//客户端事件
public delegate void WiseClientEventHandle(int i);
public event WiseClientEventHandle OnReceivePacket = null;
public event WiseClientEventHandle OnConnected = null;
public event WiseClientEventHandle OnDisconnected = null;
public delegate void WiseClientErrorHandle(string s);
public event WiseClientErrorHandle OnError = null; internal event server.WiseServerEventHandle OnServerReceivePacket = null;
internal event server.WiseServerEventHandle OnServerDisconnected = null;
internal event server.WiseServerErrorHandle OnServerError = null;
//类数据成员
internal Socket _sock;
private int _id;
private string _addr;
private int _port;
private BaseMsgHeader _MH = null;
private const int BUFFER_SIZE = 8192;
private byte[] _buffer = new byte[8192]; private List<byte[]> ReceivePacketList = new List<byte[]>();
private object ReceivePacketLock = new object(); private List<byte[]> SendPacketList = new List<byte[]>();
private object SendPacketLock = new object();
private bool _bSending = false; private byte[] _receivebuffer = new byte[16384];
private const int MAX_BUFFERSIZE = 16384;
private int _ireceive = 0; private byte[] _sendbuffer = new byte[8192];
private int _isend = 0; private AsyncCallback _connect_callback = null;
private AsyncCallback _disconnect_callback = null;
private AsyncCallback _receive_callback = null;
private AsyncCallback _send_callback = null;
//构造函数
public Client(string addr, int port)
{
_addr = addr;
_port = port;
_MH = new DefaultMsgHeader();
} public Client(string addr, int port,BaseMsgHeader msgheader)
{
_addr = addr;
_port = port;
_MH = msgheader;
} internal Client(BaseMsgHeader msgheader,int id)
{
_MH = msgheader;
_id = id;
} //断开连接
public void Disconnect()
{
try
{
if (_disconnect_callback == null)
_disconnect_callback = new AsyncCallback(disconnect_callback);
_sock.BeginDisconnect(false, _disconnect_callback, _sock);
}
catch (Exception e)
{
pdisconnect(0);
pError(e.Message);
}
} private void disconnect_callback(IAsyncResult ar)
{
Socket s;
try
{
s = (Socket)ar.AsyncState;
s.EndDisconnect(ar);
pdisconnect(1);
}
catch (Exception e)
{
pdisconnect(0);
pError(e.Message);
}
} private void pdisconnect(int i)
{
if (OnDisconnected != null)
OnDisconnected(i);
//即使服务应用程序有设置连接的OnDisconnect,也要发送信息到服务端
if (OnServerDisconnected != null)
OnServerDisconnected(_id, i);
} private void pError(string s)
{
if (OnError != null)
OnError(s);
else
if (OnServerError != null)
OnServerError(_id, s);
}
//连接
public void Connect()
{
if (_connect_callback == null)
_connect_callback = new AsyncCallback(connect_callback);
IPAddress[] ips = Dns.GetHostAddresses(_addr);
IPEndPoint remotehost = new IPEndPoint(ips[0], _port);
_sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_sock.BeginConnect(remotehost, _connect_callback, _sock);
} private void connect_callback(IAsyncResult ar)
{
Socket s;
try
{
s = (Socket)ar.AsyncState;
s.EndConnect(ar);
receive_data(s);
//if (_receive_callback == null)
// _receive_callback = new AsyncCallback(receive_callback); //s.BeginReceive(_buffer, 0, BUFFER_SIZE, 0, _receive_callback, s); if (OnConnected != null)
OnConnected(1);
}
catch (Exception e)
{
if (OnConnected != null)
OnConnected(0);
if (OnError != null) //服务端没有Connect
OnError(e.Message);
}
} //接收数据包
internal void receive_data(Socket s)
{
if (_receive_callback == null)
_receive_callback = new AsyncCallback(receive_callback); s.BeginReceive(_buffer, 0, BUFFER_SIZE, 0, _receive_callback, s);
} private void receive_callback(IAsyncResult ar)
{
Socket s;
int n;
int nDeal;
string strDebug; try
{
s = (Socket)ar.AsyncState;
n = s.EndReceive(ar); if (n + _ireceive > MAX_BUFFERSIZE)
{
strDebug = "Error RecvCallback. Buffer Overload!";
pError(strDebug);
_ireceive = 0;
}
Array.Copy(_buffer, 0, _receivebuffer, _ireceive, n);
_ireceive += n;
if (_ireceive > 0)
{
nDeal = fill_packlist(_receivebuffer,_ireceive);
if (_ireceive >= nDeal)
{
Array.Copy(_receivebuffer, nDeal, _receivebuffer, 0, _ireceive - nDeal);
_ireceive -= nDeal;
}
if (ReceivePacketList .Count > 0)
{
//通知客户程序缓冲队列有数据包
pReceiveDate(ReceivePacketList.Count);
}
}
//当接收到0字节的时候,视为远端异常,连接断开
if (n == 0)
{
pError("RecvCallback Receive 0 Bytes. ");
}
else
{
receive_data(s);
}
}
catch (Exception e)
{
pError(e.Message);
}
}
{
if (OnReceivePacket != null)
OnReceivePacket(i);
else
if (OnServerReceivePacket != null)
OnServerReceivePacket(_id, i);
}
//根据包头类定义分析接收到的缓冲数据,把它分解成数据包
//对每一个不同的包头进行处理
private int fill_packlist(byte [] b,int len)
{
if (b == null || len == 0)
return 0;
int nDeal = 0; if (_MH is DefaultMsgHeader)
{
do
{
// 查找包头标志 0xAAAAAAAA
while (len - nDeal >= 4 && BitConverter.ToUInt32(b, nDeal) != 0xAAAAAAAA)
nDeal++; if (len - nDeal < 12)
{ // 如果剩余数据不足包头长度(12字节),则返回
return nDeal;
} int packlen;
packlen = BitConverter.ToInt32(b, nDeal + 8);
if (nDeal + packlen > len)
{ // 剩余的数据不足包的长度
return nDeal;
}
else
{
byte[] packet = new byte[packlen];
Array.Copy(b, nDeal, packet, 0, packlen);
lock (ReceivePacketLock)
{
ReceivePacketList.Add(packet);
}
nDeal += packlen;
}
} while (true);
}
else if (_MH is ExchangeMsgHeader)
{
//消息头长度为16,包长int,紧跟在消息头识别后面
do
{
// 查找包头标志 0xAAAAAAAA
while (len - nDeal >= 4 && BitConverter.ToUInt32(b, nDeal) != 0xAAAAAAAA)
nDeal++; if (len - nDeal < 16)
{ // 如果剩余数据不足包头长度(12字节),则返回
return nDeal;
} int packlen;
packlen = BitConverter.ToInt32(b, nDeal + 4);
if (nDeal + packlen > len)
{ // 剩余的数据不足包的长度
return nDeal;
}
else
{
byte[] packet = new byte[packlen];
Array.Copy(b, nDeal, packet, 0, packlen);
lock (ReceivePacketLock)
{
ReceivePacketList.Add(packet);
}
nDeal += packlen;
}
} while (true);
}
else //暂时没有实现其他类
{
pError("EnCounter Unknown MsgHeader!");
return 0;
} } //发送数据
public void SendPacket(byte [] b)
{
lock (SendPacketLock)
{
if (_bSending)
{
SendPacketList.Add(b);
}
else
{
_bSending = true;
SendData(b,b.Length);
}
}
} private void SendData(byte[] data, int n)
{
try
{
if (n > 0 && data != null)
{
Array.Copy(data, 0, _sendbuffer, _isend, n);
_isend += n; if (_send_callback == null)
_send_callback = new AsyncCallback(send_callback);
_sock.BeginSend(_sendbuffer, 0, _isend, 0, _send_callback, _sock);
} }
catch (Exception e)
{
pError(e.Message);
} } private void send_callback(IAsyncResult ar)
{
Socket s;
s = (Socket)ar.AsyncState;
int n = s.EndSend(ar);
if (_isend > n)
{
Array.Copy(_sendbuffer, n, _sendbuffer, 0, _isend - n);
_isend -= n;
s.BeginSend(_sendbuffer, 0, _isend, 0, send_callback, s);
}
else
{
_isend = 0;
lock (SendPacketLock)
{
if (SendPacketList.Count > 0)
{
SendData(SendPacketList[0], SendPacketList[0].Length);
SendPacketList.RemoveAt (0);
}
else
_bSending = false;
}
}
} //关闭,释放资源
public void CloseClient()
{
_buffer = null;
ReceivePacketList = null;
ReceivePacketLock = null;
_receivebuffer = null;
SendPacketList = null;
SendPacketLock = null;
_sendbuffer = null;
if (_sock != null)
_sock.Close();
//_sock = null;
} ///获取数据包
public byte[] GetPacket()
{
if (ReceivePacketList.Count == 0 || ReceivePacketList == null)
return null;
byte[] b;
lock (ReceivePacketLock)
{
b = ReceivePacketList[0];
ReceivePacketList.RemoveAt(0);
}
return b;
} //清空接收缓冲列表
public void ClearArrived()
{
lock (ReceivePacketLock )
{
ReceivePacketList.Clear();
}
} //取得接收缓冲列表数据包数量
public int ArrivedPacketCount
{
get { return ReceivePacketList.Count; }
} //清空发送缓冲列表
public void ClearSend()
{
lock (SendPacketLock)
{
SendPacketList.Clear();
}
} //取得发送缓冲列表数据包数量
public int SendPacketCount
{
get { return SendPacketList.Count; }
} //取得连接的机器名称 ?
public string ComputerName
{
get
{
return "";
}
} ///取得连接的IP地址
public string LocalIP
{
get
{
return ((IPEndPoint)_sock.LocalEndPoint).Address.ToString ();
}
} ///取得连接的端口
public int LocalPort
{
get
{
return ((IPEndPoint)_sock.LocalEndPoint).Port;
}
} //取得标识
public int ID
{
get { return _id; }
} public EndPoint LocalEndPoint
{
get { return _sock.LocalEndPoint; }
} public EndPoint RemoteEndPoint
{
get { return _sock.RemoteEndPoint; }
} ////设置类的消息头,让server端可用
//internal BaseMsgHeader MsgHeader
//{
// get { return _MH; }
// set { _MH = value; }
//} //设置类的标识,让server端可用
//internal int ClientID
//{
// set { _id = value; }
//}
} #region 消息头
public class BaseMsgHeader
{
} public class DefaultMsgHeader : BaseMsgHeader
{
public static uint MsgMark = 0xaaaaaaaa;
protected int _eMsgType = 0;
protected int _nMsgLen = 0; public DefaultMsgHeader()
{
}
//是否需要重载,从byte[]解析出消息长度
public DefaultMsgHeader(byte[] b)
{
if (b.Length >= 12)
_nMsgLen = BitConverter.ToInt32(b, 8);
}
/// <summary>消息长度</summary>
public int Length
{
get { return _nMsgLen; }
set { _nMsgLen = value; }
}
} public class ExchangeMsgHeader : BaseMsgHeader
{
public static uint MsgMark = 0xAAAAAAAA;
protected int m_nTotalLen = 0; //消息总长度(含消息头及消息体)
protected int m_nCommandId = 0;//命令或响应类型
protected int m_nSeqId = 0; //消息流水号,顺序累加,步长为1,循环使用(一对请求和应答消息的流水号必须相同)
public ExchangeMsgHeader()
{
}
//是否需要重载,从byte[]解析出消息长度
public ExchangeMsgHeader(byte[] b)
{
if (b.Length >= 16)
m_nTotalLen = BitConverter.ToInt32(b, 4);
}
/// <summary>消息长度</summary>
public int Length
{
get { return m_nTotalLen; }
set { m_nTotalLen = value; }
}
} #endregion