请问各位大虾,在windows平台上(32bit,内存2G,双核)Socket通信最大能支持多少人同时在线,最大并发数是多少?
我做的文本聊天服务器,做压力测试时,几百人同时在线就挂了。

解决方案 »

  1.   

    理论上是由硬件决定的
    你看看是否是系统有连接数限制,如tcpip的连接
      

  2.   

    硬件当然会对最大连接数产生影响,我想知道的是,在排除硬件的影响下,最大能支持多少人同时在线。
    我用的是TCP协议,底层代码如下:
    using System;
    using System.Net;
    using System.Net.Sockets;
    using FlawlessCode.Network.ExtensionMethods;namespace FlawlessCode.Network.SocketServer
    {
        /// <summary>
        /// Listens for socket connection on a given address and port.
        /// </summary>
        public class TcpSocketListener : IDisposable
        {
            #region Fields
            private Int32 connectionBacklog;
            private IPEndPoint endPoint;        private Socket listenerSocket;
            private SocketAsyncEventArgs args;
            #endregion        #region Properties
            /// <summary>
            /// Length of the connection backlog.
            /// </summary>
            public Int32 ConnectionBacklog
            {
                get { return connectionBacklog; }
                set
                {
                    lock (this)
                    {
                        if (IsRunning)
                            throw new InvalidOperationException("Property cannot be changed while server running.");
                        else
                            connectionBacklog = value;
                    }
                }
            }
            /// <summary>
            /// The IPEndPoint to bind the listening socket to.
            /// </summary>
            public IPEndPoint EndPoint
            {
                get { return endPoint; }
                set
                {
                    lock (this)
                    {
                        if (IsRunning)
                            throw new InvalidOperationException("Property cannot be changed while server running.");
                        else
                            endPoint = value;
                    }
                }
            }
            /// <summary>
            /// Is the class currently listening.
            /// </summary>
            public Boolean IsRunning
            {
                get { return listenerSocket != null; }
            }
            #endregion        #region Constructors
            /// <summary>
            /// Listens for socket connection on a given address and port.
            /// </summary>
            /// <param name="address">The address to listen on.</param>
            /// <param name="port">The port to listen on.</param>
            /// <param name="connectionBacklog">The connection backlog.</param>
            public TcpSocketListener(String address, Int32 port, Int32 connectionBacklog)
                : this(IPAddress.Parse(address), port, connectionBacklog)
            { }
            /// <summary>
            /// Listens for socket connection on a given address and port.
            /// </summary>
            /// <param name="address">The address to listen on.</param>
            /// <param name="port">The port to listen on.</param>
            /// <param name="connectionBacklog">The connection backlog.</param>
            public TcpSocketListener(IPAddress address, Int32 port, Int32 connectionBacklog)
                : this(new IPEndPoint(address, port), connectionBacklog)
            { }
            /// <summary>
            /// Listens for socket connection on a given address and port.
            /// </summary>
            /// <param name="endPoint">The endpoint to listen on.</param>
            /// <param name="connectionBacklog">The connection backlog.</param>
            public TcpSocketListener(IPEndPoint endPoint, Int32 connectionBacklog)
            {
                this.endPoint = endPoint;
                
                args = new SocketAsyncEventArgs();
                args.Completed += SocketAccepted;
            }
            #endregion        #region Public Methods
            /// <summary>
            /// Start listening for socket connections.
            /// </summary>
            public void Start()
            {
                lock (this)
                {
                    if (!IsRunning)
                    {
                        listenerSocket = new Socket(
                            AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                        listenerSocket.Bind(endPoint);
                        listenerSocket.Listen(connectionBacklog);
                        ListenForConnection(args);
                    }
                    else
                        throw new InvalidOperationException("The Server is already running.");
                }
                
            }        /// <summary>
            /// Stop listening for socket connections.
            /// </summary>
            public void Stop()
            {
                lock (this)
                {
                    if (listenerSocket == null)
                        return;
                    listenerSocket.Close();
                    listenerSocket = null;
                }
            }
            #endregion
            
            #region Private Methods
            /// <summary>
            /// Asynchronously listens for new connections.
            /// </summary>
            /// <param name="args"></param>
            private void ListenForConnection(SocketAsyncEventArgs args)
            {
                args.AcceptSocket = null;            listenerSocket.InvokeAsyncMethod(new SocketAsyncMethod(listenerSocket.AcceptAsync)
                    , SocketAccepted, args);
            }
            /// <summary>
            /// Invoked when an asynchrounous accept completes.
            /// </summary>
            /// <param name="sender">The sender.</param>
            /// <param name="e">The SocketAsyncEventArgs for the operation.</param>
            private void SocketAccepted(object sender, SocketAsyncEventArgs e)
            {
                SocketError error = e.SocketError;
                if (e.SocketError == SocketError.OperationAborted)
                    return; //Server was stopped            if (e.SocketError == SocketError.Success)
                {
                    Socket handler = e.AcceptSocket;
                    OnSocketConnected(handler);
                }            lock (this)
                {
                    ListenForConnection(e);
                }
            }
            #endregion        #region Events
            /// <summary>
            /// Fired when a new connection is received.
            /// </summary>
            public event EventHandler<SocketEventArgs> SocketConnected;
            /// <summary>
            /// Fires the SocketConnected event.
            /// </summary>
            /// <param name="client">The new client socket.</param>
            private void OnSocketConnected(Socket client)
            {
                if (SocketConnected != null)
                    SocketConnected(this, new SocketEventArgs() { Socket = client });
            }
            #endregion        #region IDisposable Members
            private Boolean disposed = false;        ~TcpSocketListener()
            {
                Dispose(false);
            }        public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
            }        private void Dispose(bool disposing)
            {
                if (!this.disposed)
                {
                    if (disposing)
                    {
                        Stop();
                        if (args != null)
                            args.Dispose();
                    }                disposed = true;
                }
            }
            #endregion
        }
    }
      

  3.   

    using System;
    using System.Collections.Generic;
    using System.Net.Sockets;namespace FlawlessCode.Network.SocketServer
    {
        /// <summary>
        /// Pools data buffers to prevent both frequent allocation and memory fragmentation
        /// due to pinning in high volume scenarios.
        /// See https://blogs.msdn.com/yunjin/archive/2004/01/27/63642.aspx
        /// </summary>
        public class BufferPool
        {
            Int32 totalBytes;
            Byte[] buffer;
            Stack<Int32> freeIndexPool;
            Int32 currentIndex;
            Int32 bufferSize;        /// <summary>
            /// Pools data buffers to prevent both frequent allocation and memory fragmentation
            /// due to pinning in high volume scenarios.
            /// </summary>
            /// <param name="numberOfBuffers">The total number of buffers that will be allocated.</param>
            /// <param name="bufferSize">The size of each buffer.</param>
            public BufferPool(Int32 numberOfBuffers, Int32 bufferSize)
            {
                this.totalBytes = numberOfBuffers * bufferSize;
                this.bufferSize = bufferSize;            currentIndex = 0;
                freeIndexPool = new Stack<Int32>();
                buffer = new Byte[totalBytes];
            }        /// <summary>
            /// Checks out some buffer space from the pool.
            /// </summary>
            /// <param name="args">The ScoketAsyncEventArgs which needs a buffer.</param>
            public void CheckOut(SocketAsyncEventArgs args)
            {
                lock (freeIndexPool)
                {
                    if (freeIndexPool.Count > 0)
                        args.SetBuffer(buffer, freeIndexPool.Pop(), bufferSize);
                    else
                    {
                        args.SetBuffer(buffer, currentIndex, bufferSize);
                        currentIndex += bufferSize;
                    }
                }
            }        /// <summary>
            /// Checks a buffer back in to the pool.
            /// </summary>
            /// <param name="args">The SocketAsyncEventArgs which has finished with it buffer.</param>
            public void CheckIn(SocketAsyncEventArgs args)
            {
                lock (freeIndexPool)
                {
                    freeIndexPool.Push(args.Offset);
                    args.SetBuffer(null, 0, 0);
                }
            }        /// <summary>
            /// The number of available objects in the pool.
            /// </summary>
            public int Available
            {
                get
                {
                    lock (freeIndexPool)
                    { 
                        return ((totalBytes - currentIndex) / bufferSize) + freeIndexPool.Count; 
                    }
                }
            }
        }
    }
      

  4.   

    using System;
    using System.Net.Sockets;
    using FlawlessCode.Network.ExtensionMethods;
    using System.Net;namespace FlawlessCode.Network.SocketServer
    {
        /// <summary>
        /// Represents a callback used to inform a listener that a ServerConnection has received data.
        /// </summary>
        /// <param name="sender">The sender of the callback.</param>
        /// <param name="e">The DataEventArgs object containging the received data.</param>
        public delegate void DataReceivedCallback(ServerConnection sender, DataEventArgs e);
        /// <summary>
        /// Represents a callback used to inform a listener that a ServerConnection has disconnected.
        /// </summary>
        /// <param name="sender">The sender of the callback.</param>
        /// <param name="e">The SocketAsyncEventArgs object used by the ServerConnection.</param>
        public delegate void DisconnectedCallback(ServerConnection sender, SocketAsyncEventArgs e);    /// <summary>
        /// A connection to our server.
        /// </summary>
        public class ServerConnection
        {
            #region Internal Classes
            internal class State
            {
                public DataReceivedCallback dataReceived;
                public DisconnectedCallback disconnectedCallback;
                public Socket socket;
            }
            #endregion        #region Fields
            private SocketAsyncEventArgs eventArgs;
            #endregion        #region Constructor
            /// <summary>
            /// A connection to our server, always listening asynchronously.
            /// </summary>
            /// <param name="socket">The Socket for the connection.</param>
            /// <param name="args">The SocketAsyncEventArgs for asyncronous recieves.</param>
            /// <param name="dataReceived">A callback invoked when data is recieved.</param>
            /// <param name="disconnectedCallback">A callback invoked on disconnection.</param>
            public ServerConnection(Socket socket, SocketAsyncEventArgs args, DataReceivedCallback dataReceived,
                DisconnectedCallback disconnectedCallback)
            {
                lock (this)
                {
                    State state = new State() { socket = socket, dataReceived = dataReceived,
                        disconnectedCallback = disconnectedCallback};                eventArgs = args;
                    eventArgs.Completed += ReceivedCompleted;
                    eventArgs.UserToken = state;                ListenForData(eventArgs);
                }
            }
            #endregion        #region Public Methods
            /// <summary>
            /// Disconnects the client.
            /// </summary>
            public void Disconnect()
            {
                lock (this)
                {
                    CloseConnection(eventArgs);
                }
            }        /// <summary>
            /// Sends data to the client.
            /// </summary>
            /// <param name="data">The data to send.</param>
            /// <param name="offset">The offset into the data.</param>
            /// <param name="count">The ammount of data to send.</param>
            public Socket socket;
            public void SendData(Byte[] data, Int32 offset, Int32 count)
            {
                lock (this)
                {
                    State state = eventArgs.UserToken as State;
                    Socket socket = state.socket;
                    this.socket = socket;
                    if (socket.Connected)
                        socket.Send(data, offset, count, SocketFlags.None);
                }
            }
            public void SendData(Byte[] data)
            {
                lock (this)
                {
                    State state = eventArgs.UserToken as State;
                    Socket socket = state.socket;
                    this.socket = socket;
                    if (socket.Connected)
                        socket.Send(data);
                }
            }
            public void SendData(String data)
            {
                lock (this)
                {
                    State state = eventArgs.UserToken as State;
                    Socket socket = state.socket;
                    this.socket = socket;
                    Byte[] bit = System.Text.Encoding.Default.GetBytes(data + "\0");
                    if (socket.Connected)
                        socket.Send(bit);
                }
            }
            #endregion        #region Private Methods
            /// <summary>
            /// Starts and asynchronous recieve.
            /// </summary>
            /// <param name="args">The SocketAsyncEventArgs to use.</param>
            private void ListenForData(SocketAsyncEventArgs args)
            {
                lock (this)
                {
                    Socket socket = (args.UserToken as State).socket;
                    if (socket.Connected)
                    {
                        socket.InvokeAsyncMethod(socket.ReceiveAsync,
                            ReceivedCompleted, args);
                    }
                }
            }        /// <summary>
            /// Called when an asynchronous receive has completed.
            /// </summary>
            /// <param name="sender">The sender.</param>
            /// <param name="args">The SocketAsyncEventArgs for the operation.</param>
            private void ReceivedCompleted(Object sender, SocketAsyncEventArgs args)
            {
                if (args.BytesTransferred == 0)
                {
                    CloseConnection(args); //Graceful disconnect
                    return;
                }
                if (args.SocketError != SocketError.Success)
                {
                    CloseConnection(args); //NOT graceful disconnect
                    return;
                }            State state = args.UserToken as State;            Byte[] data = new Byte[args.BytesTransferred];
                Array.Copy(args.Buffer, args.Offset, data, 0, data.Length);
                OnDataReceived(data, args.RemoteEndPoint as IPEndPoint, state.dataReceived);            ListenForData(args);
            }        /// <summary>
            /// Closes the connection.
            /// </summary>
            /// <param name="args">The SocketAsyncEventArgs for the connection.</param>
            private void CloseConnection(SocketAsyncEventArgs args)
            {
                State state = args.UserToken as State;
                Socket socket = state.socket;
                try
                {
                    socket.Shutdown(SocketShutdown.Both);
                }
                catch { } // throws if client process has already closed
                socket.Close();
                socket = null;            args.Completed -= ReceivedCompleted; //MUST Remember This!
                OnDisconnected(args, state.disconnectedCallback);
            }
            #endregion        #region Events
            /// <summary>
            /// Fires the DataReceivedCallback.
            /// </summary>
            /// <param name="data">The data which was received.</param>
            /// <param name="remoteEndPoint">The address the data came from.</param>
            /// <param name="callback">The callback.</param>
            private void OnDataReceived(Byte[] data, IPEndPoint remoteEndPoint, DataReceivedCallback callback)
            {
                callback(this, new DataEventArgs() { RemoteEndPoint = remoteEndPoint, Data = data });
            }        /// <summary>
            /// Fires the DisconnectedCallback.
            /// </summary>
            /// <param name="args">The SocketAsyncEventArgs for this connection.</param>
            /// <param name="callback">The callback.</param>
            private void OnDisconnected(SocketAsyncEventArgs args, DisconnectedCallback callback)
            {
                callback(this, args);
            }
            #endregion
        }
    }
      

  5.   

    多线程非常有道理,能不能再详细一点。
    底层代码用的是缓冲池+异步通信,采用select模式,不过这种模式应该存在弊端。
      

  6.   

    硬件、系统、网络情况、尤其是TCP的应用,这些都是影响因素。
    Windows开到200个线程,性能会急剧下降的
    能开到几百个连接,已经优化得算是不错了。。==================================
    引用自一个朋友的话。。
      

  7.   

    异步通信 只是解决 server的服务效率问题,不能解决server接受连接client的数量问题。从Server设计的理论上讲,一个server可以挂无限个Client(限于硬件,不可能无限),而且不需要每一Client 都开单独的服务线程服务。一个(或若干个)线程单独监听端口,接受连接请求(挂起),挂client 到一个Client 队列里,再单独起一个线程(为了保险可以起其他线程维护这个线程)挨个服务Client队列里的client。
    也就是说,对于简单的聊天服务器,最少两个线程就可以服务了(而且服务的Client数量理论上不受限制)。
      

  8.   

    当然,有另外一种模式:
    对于Server,进来一个Client,启动一个单独的线程对其服务。这样的话,进来的Client多了,系统资源很容易被耗尽。
    祝你好运。
      

  9.   

    性能比较好的Socket, 并发量应该在2000左右
      

  10.   

    在Linux平台,性能比较好的Socket并发能达到3000~4000。
    在Windows平台,性能比较好的Socket, 同时在线人数能达多少?
      

  11.   


    windows也能支持 3000-4000 的长连接并发.
    你给的代码太长,是在难读.
      

  12.   

    补充点, windows不会比linux差,在socket上.对于好的server端来说,3000-4000是标准值.  更高也不是不可以.
      

  13.   

    首先C#的异步方法已经使用了完成端口。所以需要并发连接数上去的话,异步是一个不错的选择系统也是比较重要的一点,XP系统连接是有限制的,通常也就500个左右,再往上就没法连接了。
    至于怎么修改这个限制,还不清楚
    server2003的连接数理论上应该有65355,可到不了。
    具体最大能到多少,没有测试过。最后硬件也是有一定的关系。俺的破本子弄到300就game over了。
      

  14.   

    在用TCP长连接,单台机器能压到10000个并发左右,到12000就上不去了,CPU占用100%,IM本身服务器占用的CPU不高。
    后来发现问题出在数据库上,在做压力测试时,不停的login,logout等操作都要读写数据库,CPU都用在处理数据库上了。
     我想,如果再优化一下数据库的读写方面操作,可能还能压到更高。
      

  15.   


    这是瞎话...   直接从我这个IBM笔记本上实验的 java NIO socket 就可以连3000个...
    不知道你XP有连接500个左右的限制 这样的结论是怎么得出来的.还是你的XP系统和我的不一样么?