此爲測試用例,正式工程中包應有包頭包尾包長crc效驗等
第一步 編輔助類
public class StateObject
{
public const int BUFFER_SIZE = 10240;
public Socket workSocket;
public byte[] buffer;
public ArrayList tmpAl;
public StateObject()
{
this.workSocket = null;
this.buffer = new byte[BUFFER_SIZE];
}
~StateObject()
{
this.tmpAl = null;
this.workSocket = null;
}
}
第二步 定義變量
public static ManualResetEvent allDone = new ManualResetEvent(false);
public List<StateObject> list = new List<StateObject>();---------------------客戶端列表
private Socket serverSocket;
private SocketError errorCode;
(ManualResetEvent 允許線程通過發信號互相通信。通常,此通信涉及一個線程在其他線程進行之前必須完成的任務。當一個線程開始一個活動(此活動必須完成後,其他線程才能開始)時,它調用 Reset 以將 ManualResetEvent 置於非終止狀態,此線程可被視爲控制 ManualResetEvent。調用 ManualResetEvent 上的 WaitOne 的線程將阻止,並等待信號。當控制線程完成活動時,它調用 Set 以發出等待線程可以繼續進行的信號。並釋放所有等待線程。一旦它被終止,ManualResetEvent 將保持終止狀態(即對 WaitOne 的調用的線程將立即返回,並不阻塞),直到它被手動重置。可以通過將布爾值傳遞給構造函數來控制 ManualResetEvent 的初始狀態,如果初始狀態處於終止狀態,爲 true;否則爲 false。)
第三步 啓動程序
IPAddress[] addrIP = Dns.GetHostAddresses(Dns.GetHostName());
IPAddress ip = addrIP[0];
int myprot = 36829;
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
serverSocket.Bind(new IPEndPoint(ip, myprot));
serverSocket.Listen(1000);
第四步 開始監聽
while (true)
{
allDone.Reset();
serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), serverSocket);
allDone.WaitOne();
}
第五步 等待接受
public void AcceptCallback(IAsyncResult ar)
{
allDone.Set();
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
uint dummy = 0;--------------------------------------------------------------------------------------判斷客戶端失去連接
byte[] inOptionValues = new byte[Marshal.SizeOf(dummy) * 3];
BitConverter.GetBytes((uint)1).CopyTo(inOptionValues, 0);
BitConverter.GetBytes((uint)5000).CopyTo(inOptionValues, Marshal.SizeOf(dummy));
BitConverter.GetBytes((uint)5000).CopyTo(inOptionValues, Marshal.SizeOf(dummy) * 2);
handler.IOControl(IOControlCode.KeepAliveValues, inOptionValues, null);
StateObject state = new StateObject();
state.workSocket = handler;
state.buffer = new byte[StateObject.BUFFER_SIZE];
state.tmpAl = new ArrayList(2048);
//加入客戶端列表
if (!list.Contains(state))
{
list.Add(state);
}
handler.BeginReceive(state.buffer, 0, StateObject.BUFFER_SIZE, 0, out errorCode, new AsyncCallback(ReadCallback), state);
}
第六步 異步回調
public void ReadCallback(IAsyncResult ar)
{
string content = string.Empty;
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;
int bytesRead = 0;
try
{
bytesRead = handler.EndReceive(ar,out errorCode);
if (errorCode == SocketError.Success)
{
if (bytesRead > 0)
{
byte[] tmpbytes = new byte[bytesRead];
Array.Copy(state.buffer, 0, tmpbytes, 0, bytesRead);
state.tmpAl.AddRange(tmpbytes);
//如果此處接收的數據包長度大於BUFFER_SIZE,那麼就會出現數據包不齊,下一個數據包就會粘連!
//如果數據超過BUFFER_SIZE的大小則循環取
if (handler.Available > 0)
{
state.buffer = new byte[handler.Available];
handler.BeginReceive(state.buffer, 0, handler.Available, 0, out errorCode, new AsyncCallback(ReadCallback), state);
}
else
{
byte[] endreceive = new byte[state.tmpAl.Count];
state.tmpAl.CopyTo(endreceive);
state.tmpAl.Clear();
content = Encoding.UTF8.GetString(endreceive);
Array.Clear(endreceive, 0, endreceive.Length);
//省略處理數據
//發送給客戶端
if (!string.IsNullOrEmpty(senddata))
{
Send(handler, senddata);
}
}
}
Array.Clear(state.buffer, 0, state.buffer.Length);
handler.BeginReceive(state.buffer, 0, StateObject.BUFFER_SIZE, 0, out errorCode, new AsyncCallback(ReadCallback), state);
}
}
else
{
if (errorCode == SocketError.ConnectionReset)
{
if (state != null && !state.workSocket.Connected)
{
if (list.Contains(state))
{
list.Remove(state);
}
}
}
}
}
catch(Exception ex)
{
handler.BeginReceive(state.buffer, 0, StateObject.BUFFER_SIZE, 0, out errorCode, new AsyncCallback(ReadCallback), state);
}
}
第七步 發送數據
private void Send(Socket handler, String data)
{
byte[] byteData = Encoding.UTF8.GetBytes(data);
handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);
}
private void SendCallback(IAsyncResult ar)
{
Socket handler = (Socket)ar.AsyncState;
int bytesSent = handler.EndSend(ar, out errorCode);
if (errorCode != SocketError.Success)
{
}
}