zoukankan      html  css  js  c++  java
  • Asynchronous C# server[转]

    It hasn't been thoroughly tested, but seems to work OK.

    This should scale pretty nicely as well. Originally I was going to code it in C++, but after doing some research the scalability factor that I thought was going to gain using C++ seemed to be low considering the amount of work it was going to take.

    Server.cs

    using System;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Net.Sockets;
    using System.Net;
    
    namespace Server
    {
        
        public class Server
        {
            private int port;
            private Socket serversocket;
    
            public delegate void ConnectionEvent(Connection conn);
            public List<Connection> connections;
            public event ConnectionEvent AcceptCallback;
            public event ConnectionEvent RecieveCallback;
            public event ConnectionEvent DisconnectCallback;
    
            public Server(int p)
            {
                port = p;
                connections = new List<Connection>(500);
            }
    
            public bool Start()
            {
                IPEndPoint ipendpoint;
    
                try
                {
    
                    //do not assign an IP, as it is a server (IPAdress.Any)
                    ipendpoint = new IPEndPoint(IPAddress.Any, this.port);
    
                }
                catch (ArgumentOutOfRangeException e)
                {
                    //port was probably out of range
                    throw new ArgumentOutOfRangeException("Please check port number.", e);
    
                }
    
                try
                {
    
                    //create the main server worker socket
                    serversocket = new Socket(ipendpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
    
                }
                catch (SocketException e)
                {
    
                    //here because we couldn't create server socket
                    throw new ApplicationException("Couldn't create server socket.", e);
    
                }
    
                try
                {
                    //bind the socket to the specified port
                    serversocket.Bind(ipendpoint);
    
                    //begin listening for incoming connections
                    serversocket.Listen(100);
    
                }
                catch (SocketException e)
                {
                    
                    //probably here due to the port being in use
                    throw new ApplicationException("Couldn't bind/listen on port:  " + this.port.ToString(), e);
    
                }
    
                try
                {
    
                    //begin accepting incoming connections
                    serversocket.BeginAccept(new AsyncCallback(acceptCallback), this.serversocket);
    
                }
                catch (Exception e)
                {
                    
                    throw new ApplicationException("Error assigning the accept callback.", e);
    
                }
    
                return true;
            }
    
            private void acceptCallback(IAsyncResult ar)
            {
                Connection conn = new Connection();
    
                try
                {
                    
                    //finish the connection
    
                    //get the resulting state object
                    Socket sck = (Socket)ar.AsyncState;
                    
                    //create new connection object to be added to our concurrent connection list
                    conn = new Connection(sck.EndAccept(ar));
    
                    //lock our list for thread safety
                    lock(connections)
                    {
    
                        //add to our list
                        connections.Add(conn);
    
                    }
    
                    //begin accepting data on that socket, using our Connection object as the object state
                    conn.socket.BeginReceive(conn.buffer, 0, conn.buffer.Length, SocketFlags.None, new AsyncCallback(receiveCallback), conn);
    
                    //start accepting connections again
                    serversocket.BeginAccept(new AsyncCallback(acceptCallback), this.serversocket);
           
                    //if the eventhandler for incoming connections has been assgined, call it
                    if(AcceptCallback != null)
                    {
    
                        AcceptCallback(conn);
    
                    }
    
                }
                catch(SocketException e)
                {
                    Disconnect(conn);
                    throw new ApplicationException(e.Message, e);
                }
            }
    
            private void Disconnect(Connection conn)
            {
                //remove connection from list
                lock (connections)
                {
                    connections.Remove(conn);
                }
    
                //make sure it's completely closed
                conn.socket.Close();
    
                //if the eventhandler for disconnection has been assgined, call it
                if (DisconnectCallback != null)
                {
    
                    DisconnectCallback(conn);
    
                }
            }
    
            private void receiveCallback(IAsyncResult ar)
            {
    
                //retrieve the connection that has data ready
                Connection conn = (Connection)ar.AsyncState;
    
                try
                {
    
                    //retrieve the data(bytes) while also returning how many bytes were read
                    int bytes = conn.socket.EndReceive(ar);
    
                    
                    //if bytes is more than zero, then data was successfully read
                    if(bytes > 0)
                    {
    
                        //if the data receive callback has been assigned, call it
                        if(RecieveCallback != null)
                        {
    
                            RecieveCallback(conn);
    
                        }
    
                        //being receiving data again
                        conn.socket.BeginReceive(conn.buffer, 0, conn.buffer.Length, SocketFlags.None, new AsyncCallback(receiveCallback), conn);
    
                    }
                    else
                    {
    
                        //if zero bytes were read, connection was closed
                        Disconnect(conn);
    
                    }
                }
                catch(SocketException e)
                {
    
                    Disconnect(conn);
                    throw new ApplicationException("Error with EndReceive or BeginReceive", e);
                }
            }
        }
    }  
    View Code

    Connection.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Net.Sockets;
    
    namespace Server
    {
       
        public class Connection
        {
            public byte[] buffer;
            public Socket socket;
    
            public Connection()
            {
    
            }
            public Connection(Socket sock)
            {
                buffer = new byte[1024];
                socket = sock;
            }
    
            public void Send(string data)
            {
                try
                {
    
                    if (this.socket.Connected)
                    {
                        //convert string into an aray of bytes
                        byte[] buffer = ASCIIEncoding.ASCII.GetBytes(data);
    
                        //send our byte[] buffer
                        socket.Send(buffer, SocketFlags.None);
                    }
    
    
                }
                catch (SocketException e)
                {
                    throw new ApplicationException("Error with Send", e);
                }
            }
    
        }
    } 
    View Code

    Usage:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Threading;
    
    namespace Server
    {
        class Program
        {
            static void Main(string[] args)
            { 
                //port 80(webserver)
                Server server = new Server( 80 );
    
                server.RecieveCallback += server_RecieveCallback;
                server.AcceptCallback += server_AcceptCallback;
                server.DisconnectCallback += server_DisconnectCallback;
                server.Start();
    
                ThreadStart threadstart = new ThreadStart(ThreadJob);
                Thread thread = new Thread(threadstart);
    
                thread.Start();
    
            }
    
            static void server_DisconnectCallback(Connection conn)
            {
                Console.WriteLine("Connection disconnected
    ");
            }
    
            static void server_AcceptCallback(Connection conn)
            {
                Console.WriteLine("Incoming connection
    ");
            }
    
            static void ThreadJob()
            {
                while (true)
                    Thread.Sleep(1);
            }
    
            static void server_RecieveCallback(Connection conn)
            {
    
                Console.WriteLine(ASCIIEncoding.ASCII.GetString(conn.buffer));
    
            }
        }
    }
    View Code

    Go to your web browser and type 127.0.0.1 into the address bar.

    If any one sees any issues and things to improve on, let me know. (Sure there is).
    If any one has any questions let me know.

    不满足现状,用于挑战高峰!
  • 相关阅读:
    Linux上安装Oracle 10g 装后感
    分享16个javascript&jQuery的MVC教程
    6个出色的基于JQuery的Tab选项卡实例
    8 个高可用的 jQuery 表单验证插件
    6 套多点触摸屏的手势图标集
    PHP V5.3 中的新特性,第 4 部分: 创建并使用 Phar 归档
    精选15个国外最流行的CSS框架
    PHP V5.3 中的新特性,第 1 部分: 对象接口的变化
    分享10个便利的HTML5/CSS3框架
    XAMPP下pear安装
  • 原文地址:https://www.cnblogs.com/meyon/p/4009255.html
Copyright © 2011-2022 走看看