根据.net 3.5中的异步Socket完成的一个模块,用队列来处理tcp数据包的粘包问题,用事件将数据包通知给上层调用;

代码写的不是很好,发出来希望和大家共同交流学习。

 因为是实际项目中用的模块,所以有些地方是按照项目需求做的,大体的结构还是没问题的,除了代码写的差点外!!!

一,主要类,进行异步Socket的基本处理,.net3.5中的Socket完成端口模型的实现

    public class NET_Server : IDisposable
    {
        
private bool IsDisponse=false;
        
~NET_Server()
        {
            
this.Dispose(false);
        }
        
public void Dispose()
        {
            Dispose(
true);
            GC.SuppressFinalize(
this);  //请求系统不要调用指定对象的终结器
        }
        
protected virtual void Dispose(bool disponse)
        {
            
if (!IsDisponse)
            {
                
try {
                    
this._ServerRun = false;
                    
foreach (DictionaryEntry client in ClientsTable)
                    {
                        ((Socket)client.Value).Shutdown(SocketShutdown.Both);
                    }
                    
this.Server.Close();
                    
this.ClientsTable.Clear();
                    clientpool.poolClear();
                }
                
catch { }
                IsDisponse 
= true;
            }
        }

        
private Socket Server = null;
        
private BufferManager Buffer;
        
private SocketAsyncEventArgsPool RWpool;  //.net 3.5异步socket的关键

        
private IPEndPoint _iep;

        
private int Max_Recv_Buff_Size = 1024;    
        
private int Max_Connected_Count = 512;


        
private halfbuffpool clientpool;
        
public NET_Server(string ipsrc,int port)
        {
            _iep 
= new IPEndPoint(IPAddress.Parse(ipsrc), port);
            
this.ClientsTable = new Hashtable();
            clientpool 
= new halfbuffpool();   //管理客户端的一个数组对象

        }
        
public NET_Server(string ipsrc, int port, int nconn, int nbuff)
        {
            
//初始化
            this.Max_Recv_Buff_Size = nbuff;
            
this.Max_Connected_Count = nconn;
            _iep 
= new IPEndPoint(IPAddress.Parse(ipsrc), port);
            
this.ClientsTable = new Hashtable();
            clientpool 
= new halfbuffpool();
        }

        
//数据收发的超时时间
        private int _RecvOutTime = 3000;
        
public int RecvTimeout { get { return _RecvOutTime; } set { _RecvOutTime = value; } }
        
private int _SendTimeout = 1000;
        
public int SendTimeout { get { return _SendTimeout; } set { _SendTimeout = value; } }


        
public event ServerEventHandler Notification;
        
//开启服务器
        public bool StartServer()
        {
            
this._ServerRun = true;
            
this.Server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            
bool result = false;
            
if (IsDisponse)
            {
                
throw new ObjectDisposedException("Server is Disponse!");
            }
            
try
            {
                
// 设定与服务器相关参数
                this.Server.Bind(this._iep);
                
this.Server.Listen(5);
                
this.Server.SendTimeout = this._SendTimeout;
                
this.Server.ReceiveTimeout = this._RecvOutTime;
                result 
= true;
                
//创建并初始化缓冲区管理对象
                Buffer = new BufferManager(this.Max_Connected_Count*this.Max_Recv_Buff_Size, this.Max_Recv_Buff_Size);
                Buffer.Inint();
                
//构造SocketAsyncEventArgs池
                RWpool = new SocketAsyncEventArgsPool(this.Max_Connected_Count);
                
for (int i = 0; i < this.Max_Connected_Count;i++)
                {
                    SocketAsyncEventArgs asyniar 
= new SocketAsyncEventArgs();
                    asyniar.Completed 
+= new EventHandler<SocketAsyncEventArgs>(Asyn_Completed);
                    RWpool.Push(asyniar);
                }
                Console.WriteLine(
"Begin Listen....");
                Accept();  
            }
            
catch (Exception ex) { Notification(nullnew ServerEventArgs(ArgsType.EXCEPTION, ex.Message,null));}
            
return result;
        }
        
private void Accept()  //开始接受连接
        {
            
if (!_ServerRun) return;
            
if (RWpool.Count > 0
            {
                SocketAsyncEventArgs asyniar 
= RWpool.Pop();
                
if (!Server.AcceptAsync(asyniar)) //弹出一个SocketAsyncEventArgs对象开始AcceptAsyn
                {
                    BeginAccep(asyniar);      
                    
//如果I/O挂起等待异步则触发AcceptAsyn_Asyn_Completed事件
                    
//此时I/O操作同步完成,不会触发Asyn_Completed事件,所以指定BeginAccept()方法
                }   
            }
            
else
            {
                Console.WriteLine(
"Had Max Connected!");
            }
        }

        
private Hashtable ClientsTable;
        
private void BeginAccep(SocketAsyncEventArgs e)
        {
            
try
            {
                
if (e.SocketError == SocketError.Success)
                {
                    
string clientip=string.Format("{0}",((IPEndPoint)e.AcceptSocket.RemoteEndPoint).Address);
                    
if (ClientsTable.Contains(clientip))
                    {
                        e.AcceptSocket.Shutdown(SocketShutdown.Both);
                        e.AcceptSocket 
= null;   //保持SocketAsynEventArgs池 的堆栈平衡
                        RWpool.Push(e);
                        
return;
                    }
                    
else
                        
this.ClientsTable.Add(clientip, e.AcceptSocket);
                    Notification(
nullnew ServerEventArgs(ArgsType.CLIENTCONN, clientip,null));
                    
//查找客户如果不存在,则添加一个新客户
                    halfbuff client = clientpool.GetClient((IPEndPoint)e.AcceptSocket.RemoteEndPoint);
                    
if (client == null)
                    {
                        client 
= new halfbuff((IPEndPoint)e.AcceptSocket.RemoteEndPoint);
                        client.HalfEvent 
+= new EventHandler<HaflBuffEventArgs>(OnHalfEvent);
                        clientpool.poolAdd(client);
                    }
                    clientpool.poolAdd(client);
                    
//接受一个连接,发送欢迎信息
                    e.AcceptSocket.Send(Encoding.ASCII.GetBytes("send"));
                    
if (Buffer.SetBuffer(e))
                    {
                        
if (!e.AcceptSocket.ReceiveAsync(e))  //是否触发 Asyn_Commpleted事件
                        {
                            BeginReceive(e);
                        }
                    }
                }
                
else
                {
                    e.AcceptSocket 
= null;   //保持SocketAsynEventArgs池 的堆栈平衡
                    RWpool.Push(e);
                    Console.WriteLine(
"Not Accept!");
                }
            }
               
catch(Exception ex){
                   e.AcceptSocket 
= null;   //保持SocketAsynEventArgs池 的堆栈平衡
                   RWpool.Push(e);
                   Notification(
nullnew ServerEventArgs(ArgsType.EXCEPTION, ex.Message, null));
               }
            
finally
            {
                Accept();
            }

        }
        
private void OnHalfEvent(object sender,HaflBuffEventArgs e)
        {
            Notification(
nullnew ServerEventArgs(ArgsType.RECEIVE, "", e.BUFF));
        }
        
private bool _debug = false;
        
public bool Debug { get { return _debug; } set { _debug = value; } }
        
private void BeginReceive(SocketAsyncEventArgs e)
        {
            halfbuff client 
= clientpool.GetClient((IPEndPoint)e.AcceptSocket.RemoteEndPoint);
            
if (e.SocketError == SocketError.Success && e.BytesTransferred > 0)
            {
                
byte[] data = new byte[e.BytesTransferred];
                Array.Copy(e.Buffer, e.Offset, data, 
0, data.Length);//从e.Buffer块中复制数据出来,保证它可重用
                if(_debug)
                    Notification(
nullnew ServerEventArgs(ArgsType.DEBUG, "debug",data));
                
if (data.Length>3)  //排除心跳包 01
                {
                    
if (client != null)
                        client.pool.Enqueue(data);
                }
                
if (!e.AcceptSocket.ReceiveAsync(e))
                {
                    BeginReceive(e); 
//
                }
            }
            
else
            {
                
string clientip=string.Format("{0}",((IPEndPoint)e.AcceptSocket.RemoteEndPoint).Address);
                
this.ClientsTable.Remove(clientip);
                Console.WriteLine(
"A Client Disconnected,{0}",e.AcceptSocket.RemoteEndPoint);
                Notification(
nullnew ServerEventArgs(ArgsType.CLIENTDISCONN, clientip,null));
                
//查找客户存在,则删除客户
                if (client!=null)
                {
                    
//e.AcceptSocket.Shutdown(SocketShutdown.Both);
                    clientpool.poolDel(client);
                }
                e.AcceptSocket 
= null;
                Buffer.FreeBuffer(e);
                RWpool.Push(e);
                
if (RWpool.Count == 1)
                {
                    Accept();
                }
            }

        }
       
        
private void Asyn_Completed(object sender, SocketAsyncEventArgs e)
        {
            
switch (e.LastOperation)
            {
                
case SocketAsyncOperation.Accept:
                    BeginAccep(e);
                    
break;
                
case SocketAsyncOperation.Receive:
                    BeginReceive(e);
                    
break;

            }

        }
        
private bool _ServerRun = true;
        
public bool ServerRun { get { return _ServerRun; } set { _ServerRun = value; } }
        
public void StopServer()
        {
            
this._ServerRun = false;
            
foreach (DictionaryEntry client in ClientsTable)
            {
                ((Socket)client.Value).Shutdown(SocketShutdown.Both);
            }
            
if(this.Server!=null)
            
this.Server.Close();
            
this.ClientsTable.Clear();
            Console.WriteLine(
"The Server Stoped!");
        }
}

相关文章: