c# Socket 的应用
---------------AjaxBaseSocket.cs--------------
public abstract class AjaxBaseSocket : IDisposable
{
protected Socket _socket;
protected AjaxBaseSocket(IPEndPoint ipAddress)
{
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
protected abstract void Close();
#region IDisposable Members
public void Dispose()
{
Close();
GC.SuppressFinalize(this);
}
#endregion
}
------AjaxMessage.cs----------------
public sealed class AjaxMessage:EventArgs
{
private int _key;
private string _body;
public AjaxMessage(int key,string content):base()
{
_key = key;
_body = content;
}
public int Key
{
get { return _key; }
}
public string Body
{
get { return _body; }
}
}
---------------------AjaxMessageHelper.cs-----------------
public sealed class AjaxMessageHelper
{
public static readonly byte[] MessageSeperate = new byte[]{159,187,169,175,
141,184,17,73,
182,159,124,238,
167,208,193,196};
public sealed class Crc16
{
const ushort polynomial = 0xA001;
ushort[] table = new ushort[] {
0,94,188,226,97,63,221,131,194,156,126,32,163,253,31,65,
157,195,33,127,252,162,64,30, 95,1,227,189,62,96,130,220,
35,125,159,193,66,28,254,160,225,191,93,3,128,222,60,98,
190,224,2,92,223,129,99,61,124,34,192,158,29,67,161,255,
70,24,250,164,39,121,155,197,132,218,56,102,229,187,89,7,
219,133,103,57,186,228,6,88,25,71,165,251,120,38,196,154,
101,59,217,135,4,90,184,230,167,249,27,69,198,152,122,36,
248,166,68,26,153,199,37,123,58,100,134,216,91,5,231,185,
140,210,48,110,237,179,81,15,78,16,242,172,47,113,147,205,
17,79,173,243,112,46,204,146,211,141,111,49,178,236,14,80,
175,241,19,77,206,144,114,44,109,51,209,143,12,82,176,238,
50,108,142,208,83,13,239,177,240,174,76,18,145,207,45,115,
202,148,118,40,171,245,23,73,8,86,180,234,105,55,213,139,
87,9,235,181,54,104,138,212,149,203, 41,119,244,170,72,22,
233,183,85,11,136,214,52,106,43,117,151,201,74,20,246,168,
116,42,200,150,21,75,169,247,182,232,10,84,215,137,107,53
};
public ushort ComputeChecksum(byte[] bytes)
{
ushort crc = 0;
for (int i = 0; i < bytes.Length; i++)
{
byte index = (byte)(crc ^ bytes[i]);
crc = (ushort)((crc >> 8) ^ table[index]);
}
return crc;
}
public byte[] ComputeChecksumBytes(byte[] bytes)
{
ushort crc = ComputeChecksum(bytes);
return new byte[] { (byte)(crc >> 8), (byte)(crc & 0x00ff) };
}
public Crc16()
{
}
}
--------------------取之网上,对不对我也不知道,不过,同样的数据,就算是算法错误,得到的结果也应该一样,
static Crc16 crc;
private AjaxMessageHelper()
{
}
static AjaxMessageHelper()
{
crc = new Crc16();
}
public static byte[] ToByte(AjaxMessage message)
{
string txt = message.Body;
byte[] body = System.Text.Encoding.Unicode.GetBytes(message.Body);
ushort checkSum = crc.ComputeChecksum(body);
byte[] checkBytes=BitConverter.GetBytes(checkSum );
byte[] lenData = BitConverter.GetBytes(body.Length);
byte[] data = new byte[26 + body.Length];
//Copy Sepearte
Array.Copy(MessageSeperate, data, 16);
byte[] key = BitConverter.GetBytes(message.Key);
//Copy key
for (int i = 16; i < 20; i++)
{
data[i] = key[i - 16];
}
///Copy BodyLenght
for (int i = 20; i < 24; i++)
{
data[i] = lenData[i - 20];
}
///copy CheckByte
for (int i = 24; i < 26; i++)
{
data[i] = checkBytes[i - 24];
}
//Copy data
Array.Copy(body, 0, data, 26, body.Length);
return data;
}
public static AjaxMessage ToMessage(byte[] data)
{
AjaxMessage ajMsg = null;
int key = BitConverter.ToInt32(data, 16);
int len = BitConverter.ToInt32(data, 20);
string msg = System.Text.Encoding.Unicode.GetString(data, 26, len);
ajMsg = new AjaxMessage(key, msg);
return ajMsg;
}
/// <summary>
/// 是不是一个完整的数据包
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public static bool CompletedPacket(byte[] data)
{
if (data.Length < 26)
return false;
for (int i = 0; i < 16; i++)
{
if (data[i] != MessageSeperate[i])
{
Console.WriteLine("MessageSeperate");
return false;
}
}
int len = BitConverter.ToInt32(data, 20);
if (len + 26 != data.Length)
return false ;
ushort check = BitConverter.ToUInt16(data, 24);
byte[] tmp = new byte[len];
Array.Copy(data, 26, tmp, 0, len);
ushort c2 = crc.ComputeChecksum(tmp);
if (check != c2)
{
Console.WriteLine("Check");
return false;
}
if (data.Length == len + 26)
{
Console.WriteLine("Len");
return true;
}
else
{
return false;
}
}
public static int BoundaryIndex(byte[] data, int startPos)
{
if (data.Length < AjaxMessageHelper.MessageSeperate.Length)
return -1;
int bIndex = 0;
int bLen = AjaxMessageHelper.MessageSeperate.Length;
int iPos = startPos;
int lc = data.Length;
bool bEind = false;
while ((iPos < lc) && (bEind == false))
{
if (data[iPos] == AjaxMessageHelper.MessageSeperate[bIndex])
{
bIndex++;
}
else
{
bIndex = 0;
}
if (bIndex == bLen)
{
bEind = true;
}
iPos++;
}
if (bEind)
{
return iPos - 16;
}
else
{
return -1;
}
}
}
AjaxServerSocket.cs
public delegate void AjaxMessageArrivedEventHandle(WorkerSocket w,AjaxMessage msg);
public delegate void AjaxSocketClientConnectedEventHandle(WorkerSocket w);
public class AjaxServerSocket:AjaxBaseSocket
{
static ManualResetEvent mr = new ManualResetEvent(true);
public event AjaxMessageArrivedEventHandle AjaxMessageArrived;
public event AjaxSocketClientConnectedEventHandle AjaxClientConnected;
public event AjaxMessageArrivedEventHandle AjaxMessageSendCompleted;
public AjaxServerSocket(IPEndPoint ipAddress)
: base(ipAddress)
{
_socket.Bind(ipAddress);
}
private void accepteCallback(IAsyncResult ar)
{
Socket server = ar.AsyncState as Socket;
Socket handler = server.EndAccept(ar);
mr.Set();
WorkerSocket ws = new WorkerSocket(handler);
if (AjaxClientConnected != null)
{
AjaxClientConnected(ws);
}
ws.AjaxMessageParseOk += new EventHandler<AjaxMessage>(ws_AjaxMessageParseOk);
ws.AjaxMessageSendOk += new EventHandler<AjaxMessage>(ws_AjaxMessageSendOk);
ws.Read();
}
void ws_AjaxMessageSendOk(object sender, AjaxMessage e)
{
if (AjaxMessageSendCompleted != null)
{
AjaxMessageSendCompleted((WorkerSocket)sender, e);
}
}
void ws_AjaxMessageParseOk(object sender, AjaxMessage e)
{
if (AjaxMessageArrived != null)
{
WorkerSocket ws = sender as WorkerSocket;
AjaxMessageArrived(ws, e);
}
}
public void Run()
{
_socket.Listen(1000);
while (true)
{
mr.Reset();
Console.WriteLine("Waiting for connecting...");
_socket.BeginAccept(new AsyncCallback(accepteCallback), _socket);
mr.WaitOne();
}
}
protected override void Close()
{
_socket.Shutdown(SocketShutdown.Both);
_socket.Close(30000);
}
}
----------------------WorkerSocket.cs--------------------
public class WorkerSocket:IDisposable
{
private ManualResetEvent readHandle = new ManualResetEvent(true);
private ManualResetEvent sendHandle = new ManualResetEvent(true);
private ManualResetEvent mr = new ManualResetEvent(true);
private ManualResetEvent mw = new ManualResetEvent(true);
public event EventHandler<AjaxMessage> AjaxMessageParseOk;
public event EventHandler<AjaxMessage> AjaxMessageSendOk;
public event EventHandler ReadCompleted;
private Socket worker;
private MemoryStream ms;
private byte[] buffer;
public WorkerSocket(Socket socket)
{
worker = socket;
ms = new MemoryStream();
buffer = new byte[1024];
}
public EventWaitHandle ReadHandle
{
get
{
return readHandle;
}
}
public EventWaitHandle SendHandle
{
get
{
return sendHandle;
}
}
private void Add(byte[] readData)
{
mr.WaitOne();
mw.Reset();
try
{
mr.Reset();
try
{
ms.Write(readData, 0, readData.Length);
byte[] data = ms.ToArray();
int st = AjaxMessageHelper.BoundaryIndex(data, 0);
if (st == -1)
{
ms.Write(readData, 0, readData.Length);
}
else
{
int nextStart = AjaxMessageHelper.BoundaryIndex(data, st + 26);
AjaxMessage msg = null;
while (nextStart != -1)
{
byte[] tmp = new byte[nextStart - st];
Array.Copy(data, st, tmp, 0, nextStart - st);
if (AjaxMessageHelper.CompletedPacket(tmp))
{
msg = AjaxMessageHelper.ToMessage(tmp);
}
else
{
msg = new AjaxMessage(0, "DataPacketError");
}
if (AjaxMessageParseOk != null)
{
AjaxMessageParseOk(this, msg);
}
st = nextStart;
nextStart = AjaxMessageHelper.BoundaryIndex(data, st + 26);
}
int len = data.Length;
int leftLen = len - st;
byte[] left = new byte[leftLen];
Array.Copy(data, st, left, 0, leftLen);
if (AjaxMessageHelper.CompletedPacket(left))
{
msg = AjaxMessageHelper.ToMessage(left);
if (AjaxMessageParseOk != null)
{
AjaxMessageParseOk(this, msg);
}
ms.Seek(0, SeekOrigin.Begin);
ms.SetLength(0);
}
else
{
ms.Seek(0, SeekOrigin.Begin);
ms.Write(left, 0, leftLen);
ms.SetLength(leftLen);
}
}
}
finally
{
mr.Set();
}
}
finally
{
mw.Set();
}
}
private void receiveCallback(IAsyncResult ar)
{
int read =worker.EndReceive(ar);
if (read != 0)
{
byte[] tmp = new byte[read];
Array.Copy(this.buffer, tmp, read);
this.Add(tmp);
worker.BeginReceive(buffer, 0, 1024, SocketFlags.None, new AsyncCallback(receiveCallback), null);
}
else
{
if (this.ReadCompleted != null)
{
this.ReadCompleted(this, EventArgs.Empty);
}
readHandle.Set();
}
}
public void Read()
{
readHandle.Reset();
worker.BeginReceive(buffer, 0, 1024, SocketFlags.None, new AsyncCallback(receiveCallback), null);
}
private void sendCallback(IAsyncResult ar)
{
SendState s = ar.AsyncState as SendState;
int i = worker.EndSend(ar);
int gcd = s.Len / 1024;
int left = s.Len % 1024;
s.Order = s.Order + 1;
if (s.Order < gcd)
{
worker.BeginSend(s.Data, s.Order * 1024, 1024, SocketFlags.None, new AsyncCallback(sendCallback), s);
}
else if (s.Order == gcd)
{
worker.BeginSend(s.Data, s.Order * 1024, left, SocketFlags.None, new AsyncCallback(sendCallback), s);
}
else
{
sendHandle.Set();
if (AjaxMessageSendOk != null)
{
AjaxMessageSendOk(this, s.Msg);
}
}
}
public void SendMessage(AjaxMessage msg)
{
byte[] d = AjaxMessageHelper.ToByte(msg);
sendHandle.Reset();
SendState s = new SendState(d, 0,msg);
AsyncCallback cb = new AsyncCallback(sendCallback);
if (d.Length <= 1024)
{
worker.BeginSend(d, 0, d.Length, SocketFlags.None, cb, s);
}
else
{
worker.BeginSend(d, 0, 1024, SocketFlags.None, cb, s);
}
}
internal class SendState
{
public byte[] Data;
private int len;
private int order;
private AjaxMessage _msg;
public AjaxMessage Msg
{
get
{
return _msg;
}
}
public int Len
{
get
{
return len;
}
}
public int Order
{
get
{
return order;
}
set
{
order = value;
}
}
public SendState(byte[] data, int orders,AjaxMessage msg)
{
Data = data;
len = data.Length;
order = orders;
_msg = msg;
}
}
public Socket Worker
{
get
{
return worker;
}
}
#region IDisposable Members
public void Dispose()
{
if (ms != null)
{
ms.Close();
}
if (worker != null)
{
worker.Shutdown(SocketShutdown.Both);
worker.Close();
}
}
#endregion
}
--------------------------Server---------------------------------
class Program
{
static List<EventWaitHandle> lstMr = new List<EventWaitHandle>();
static List<EventWaitHandle> lstMs = new List<EventWaitHandle>();
static void Main(string[] args)
{
IPEndPoint ipend = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 5959);
using (AjaxSocket.AjaxServerSocket s = new AjaxSocket.AjaxServerSocket(ipend))
{
s.AjaxClientConnected += new AjaxSocket.AjaxSocketClientConnectedEventHandle(s_AjaxClientConnected);
s.AjaxMessageArrived += new AjaxSocket.AjaxMessageArrivedEventHandle(s_AjaxMessageArrived);
s.Run();
EventWaitHandle.WaitAll(lstMr.ToArray());
}
}
static void s_AjaxMessageArrived(AjaxSocket.WorkerSocket w, AjaxSocket.AjaxMessage msg)
{
Console.WriteLine("{0}:{1}", msg.Key, msg.Body);
}
static void s_AjaxClientConnected(AjaxSocket.WorkerSocket w)
{
lstMr.Add(w.ReadHandle);
lstMs.Add(w.SendHandle);
}
}
-------------------------Client----------------------------
static void Main(string[] args)
{
string[] mes = new string[]{
"SOGOU推广服务",
"美国伟哥给你强大性能力!(图)性爱延时30分钟,三倍的硬度让她高潮迭起,美国原产伟哥,全球1.4亿人见证,原产正品,假一罚十",
"九酷免费电影--中国大而全的免费电影网站九酷免费电影网提供最新的,最全的电影在线观看,免费电影下载,欧美,港台,内地,日韩,恐怖等.. ",
"30天阴茎增大8cm低价促销阴茎增大胶囊全球畅销的男根增大产品,回馈新老客户 超值赠品 任选.给您带来男根增大3英寸的奇迹! 两性治疗.. ",
"永华电池,永放光华!我们是专业生产碱性电池及碱性电池机械制造的一个综合性企业,产品质量通过了ISO9001:2000国际.. ",
"引言CRC的全称为Cyclic Redundancy Check,中文名称为循环冗余校验。它是一类重要的线性分组码编码和解码方法简单,检错和纠错能力强,在通信领域广泛地用于实现差错控制。实际上,除数据通信外,CRC在其它很多领域也是大有用武之地的。例如我们读软盘上的文件,以及解压一个ZIP文件时,偶尔会碰到“Bad CRC”错误,由此它在数据存储方面的应用可略见一斑。差错控制理论是在代数理论基础上建立起来的。这里我们着眼于介绍CRC的算法与实现,对原理只能捎带说明一下。若需要进一步了解线性码、分组码、循环码、纠错编码等方面的原理,可以阅读有关资料。利用CRC进行检错的过程可简单描述为:在发送端根据要传送的k位二进制码序列,以一定的规则产生一个校验用的r位监督码(CRC码),附在原始信息后边,构成一个新的二进制码序列数共k+r位,然后发送出去。在接收端,根据信息码和CRC码之间所遵循的规则进行检验,以确定传送中是否出错。这个规则,在差错控制理论中称为引言CRC的全称为Cyclic Redundancy Check,中文名称为循环冗余校验。它是一类重要的线性分组码,编码和解码方法简单,检错和纠错能力强,在通信领域广泛地用于实现差错控制。实际上,除数据通信外,CRC在其它很多领域也是大有用武之地的。例如我们读软盘上的文件,以及解压一个ZIP文件时,偶尔会碰到“Bad CRC”错误,由此它在数据存储方面的应用可略见一斑。差错控制理论是在代数理论基础上建立起来的。这里我们着眼于介绍CRC的算法与实现,对原理只能捎带说明一下。若需要进一步了解线性码、分组码、循环码、纠错编码等方面的原理,可以阅读有关资料。利用CRC进行检错的过程可简单描述为:在发送端根据要传送的k位二进制码序中文名称为循环冗余校验。它是一类重要的线性分组码编码和解码方法简单,检错和纠错能力强,在通信领域广泛地用于实现差错控制。实际上,除数据通信外,CRC在其它很多领域也是大有用武之地的。例如我们读软盘上的文件,以及解压一个ZIP文件时,偶尔会碰到“Bad CRC”错误,由此它在数据存储方面的应用可略见一斑。差错控制理论是在代数理论基础上建立起来的。这里我们着眼于介绍CRC的算法与实现,对原理只能捎带说明一下。若需要进一步了解线性码、分组码、循环码、纠错编码等方面的原理,可以阅读有关资料。利用CRC进行检错的过程可简单描述为:在发送端根据要传送的k位二进制码序列,以一定的规则产生一个校验用的r位监督码(CRC码),附在原始信息后边,构成一个新的二进制码序列数共k+r位,然后发送出去。在接收端,根据信息码和CRC码之间所遵循的规则进行检验,以确定传送中是否出错。这个规则,在差错控制理论中称为引言CRC的全称为Cyclic Redundancy Check,中文名称为循环冗余校验。它是一类重要的线性分组码,编码和解码方法简单,检错和纠错能力强,在通信领域广泛地用于实现差错控制。实际上,除数据通信外,CRC在其它很多领域也是大有用武之地的。例如我们读软盘上的文件,以及解压一个ZIP文件时,偶尔会碰到“Bad CRC”错误,由此它在数据存储方面的应用可略见一斑。差错控制理论是在代数理论基础上建立起来的。这里我们着眼于介绍CRC的算法与实现,对原理只能捎带说明一下。若需要进一步了解线性码、分组码、循环码、纠错编码等方面的原理,可以阅读有关资料。利用CRC进行检错的过程可简单描述为:在发送端根据要传送的k位二进制码序",
};
IPEndPoint ipend = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 5959);
Random rd=new Random();
using (AjaxSocket.AjaxClientSocket cs = new AjaxSocket.AjaxClientSocket(ipend))
{
cs.SendCompleted += new EventHandler(cs_SendCompleted);
int i = 1;
foreach (string s in mes)
{
AjaxSocket.AjaxMessage msg = new AjaxSocket.AjaxMessage(16 + i, "Message: " + s);
cs.SendMessage(msg);
i++;
System.Threading.Thread.Sleep(1000);
}
System.Threading.Thread.Sleep(1000);
}
}
static void cs_SendCompleted(object sender, EventArgs e)
{
Console.WriteLine("SendOk");
}
}
-------------------------------------------OVER------------------------
VS2008 + Win Vista Sp1