C#套接字服务器 - 并发连接问题

时间:2011-04-23 14:08:32

标签: c# .net flash sockets

嘿所有, 我在C#中创建了一个用于我正在开发的Flash游戏的套接字服务器,我从某处获得了代码,我是c#和.net开发的初学者。在进行连接并且服务器正常运行时,它在实践中工作正常。同时获得2个并发连接,我们遇到了问题。

下面是socket服务器的基本方面:(由于显而易见的原因,很多时候已经取出)

如何更改此设置以便它可以处理并发连接?我应该对每个回复进行线程化吗?

由于

class TcpSock { int tcpIndx = 0; int tcpByte = 0;

    byte[] tcpRecv = new byte[1024];

    ////////////////////////////////////////
    public Socket tcpSock;
    ////////////////////////////////////////

    public int Recv(ref string tcpRead)
    {
        tcpByte = tcpSock.Available;
        if (tcpByte > tcpRecv.Length - tcpIndx)
            tcpByte = tcpRecv.Length - tcpIndx;

        tcpByte = tcpSock.Receive(tcpRecv, tcpIndx, tcpByte,
            SocketFlags.Partial);
        tcpRead = Encoding.ASCII.GetString
            (tcpRecv, tcpIndx, tcpByte);
        tcpIndx += tcpByte;
        return tcpRead.Length;
    }

    public int RecvLn(ref string tcpRead)
    {
        tcpRead = Encoding.ASCII.GetString
            (tcpRecv, 0, tcpIndx);
        tcpIndx = 0;
        return tcpRead.Length;
    }

    public int Send(string tcpWrite)
    {
        return tcpSock.Send(Encoding.ASCII.GetBytes(tcpWrite));
    }

    public int SendLn(string tcpWrite)
    {
        return tcpSock.Send(Encoding.ASCII.GetBytes(tcpWrite + "\r\n"));
    }


}

byte[] tcpRecv = new byte[1024]; //////////////////////////////////////// public Socket tcpSock; //////////////////////////////////////// public int Recv(ref string tcpRead) { tcpByte = tcpSock.Available; if (tcpByte > tcpRecv.Length - tcpIndx) tcpByte = tcpRecv.Length - tcpIndx; tcpByte = tcpSock.Receive(tcpRecv, tcpIndx, tcpByte, SocketFlags.Partial); tcpRead = Encoding.ASCII.GetString (tcpRecv, tcpIndx, tcpByte); tcpIndx += tcpByte; return tcpRead.Length; } public int RecvLn(ref string tcpRead) { tcpRead = Encoding.ASCII.GetString (tcpRecv, 0, tcpIndx); tcpIndx = 0; return tcpRead.Length; } public int Send(string tcpWrite) { return tcpSock.Send(Encoding.ASCII.GetBytes(tcpWrite)); } public int SendLn(string tcpWrite) { return tcpSock.Send(Encoding.ASCII.GetBytes(tcpWrite + "\r\n")); } }

[STAThread] static void Main() {

        Thread Server1 = new Thread(RunServer);
        Server1.Start();

    }

    static void RunServer()
    {


        ///class IPHostEntry : Stores information about the Host and is required
        ///for IPEndPoint.
        ///class IPEndPoint  : Stores information about the Host IP Address and
        ///the Port number.
        ///class TcpSock     : Invokes the constructor and creates an instance.
        ///class ArrayList   : Stores a dynamic array of Client TcpSock objects.

        IPHostEntry Iphe = Dns.Resolve(Dns.GetHostName());
        IPEndPoint Ipep = new IPEndPoint(Iphe.AddressList[0], 4444);
        Socket Server = new Socket(Ipep.Address.AddressFamily,SocketType.Stream, ProtocolType.Tcp);


        ///Initialize
        ///Capacity : Maximux number of clients able to connect.
        ///Blocking : Determines if the Server TcpSock will stop code execution
        ///to receive data from the Client TcpSock.
        ///Bind     : Binds the Server TcpSock to the Host IP Address and the Port Number.
        ///Listen   : Begin listening to the Port; it is now ready to accept connections.

        ArrayList Client = new ArrayList();

        string[,] Users = new string[1000,9];

        string rln = null;

        string[] Data;


        Client.Capacity = 1000;



        Server.Blocking = false;
        Server.Bind(Ipep);
        Server.Listen(32);

        Console.WriteLine("Server 1 {0}: listening to port {1}", Dns.GetHostName(), Ipep.Port);

        ////////////////////////////////////////////////////////////////////////////////////////////
        ///Main loop
        ///1. Poll the Server TcpSock; if true then accept the new connection.
        ///2. Poll the Client TcpSock; if true then receive data from Clients.

        while (true)
        {
            //Accept - new connection

            #region new connection
            if (Server.Poll(0, SelectMode.SelectRead))
            {
                int i = Client.Add(new TcpSock());



                ((TcpSock)Client[i]).tcpSock = Server.Accept();
                Console.WriteLine("Client " + i + " connected.");


                Users[i, 0] = i.ToString();


            }
            #endregion 

            for (int i = 0; i < Client.Count; i++)
            {
                //check for incoming data
                if (((TcpSock)Client[i]).tcpSock.Poll(0, SelectMode.SelectRead))
                {
                    //receive incoming data
                    if (((TcpSock)Client[i]).Recv(ref rln) > 0)
                    {
                        Console.WriteLine(rln.ToString());
                        Data = rln.Split('|');

                        // 1) initial connection
                        #region InitialConnection

                        if (Data[0] == "0000")

                        {

                        }



                   }
               }
         }
    }

3 个答案:

答案 0 :(得分:1)

您将不需要使用同步函数,但需要使用像Socket.BeginReceive这样的asynchrounus函数

答案 1 :(得分:0)

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
public static partial class TcpServer
{
    public static void Main()
    {
        // Setup listener on "localhost" port 12000
        IPAddress ipAddr = Dns.GetHostEntry("localhost").AddressList[0];
        TcpListener server = new TcpListener(ipAddr, 12000);
        server.Start(); // Network driver can now allow incoming requests 

        // Accept up to 1 client per CPU simultaneously
        Int32 numConcurrentClients = Environment.ProcessorCount;

        for (Int32 n = 0; n 

    private static Byte[] ProcessData(Byte[] inputData)
    {
        String inputString = Encoding.UTF8.GetString(inputData, 1, inputData[0]);
        String outputString = inputString.ToUpperInvariant();

        Console.WriteLine("Input={0}", inputString);
        Console.WriteLine("   Output={0}", outputString);
        Console.WriteLine();

        Byte[] outputStringBytes = Encoding.UTF8.GetBytes(outputString);
        Byte[] outputData = new Byte[1 + outputStringBytes.Length];
        outputData[0] = (Byte)outputStringBytes.Length;
        Array.Copy(outputStringBytes, 0, outputData, 1, outputStringBytes.Length);
        return outputData;
    }
}
public static partial class TcpServer
{
    private sealed class ClientConnectionApm
    {
        private TcpListener m_server;
        private TcpClient m_client;
        private Stream m_stream;
        private Byte[] m_inputData = new Byte[1];
        private Byte m_bytesReadSoFar = 0;
        public ClientConnectionApm(TcpListener server)
        {
            m_server = server;
            m_server.BeginAcceptTcpClient(AcceptCompleted, null);
        }
        private void AcceptCompleted(IAsyncResult ar)
        {
            // Connect to this client
            m_client = m_server.EndAcceptTcpClient(ar);

            // Accept another client
            new ClientConnectionApm(m_server);

            // Start processing this client
            m_stream = m_client.GetStream();
            // Read 1 byte from client which contains length of additional data
            m_stream.BeginRead(m_inputData, 0, 1, ReadLengthCompleted, null);
        }
        private void ReadLengthCompleted(IAsyncResult result)
        {
            // If client closed connection; abandon this client request
            if (m_stream.EndRead(result) == 0) { m_client.Close(); return; }

            // Start to read 'length' bytes of data from client
            Int32 dataLength = m_inputData[0];
            Array.Resize(ref m_inputData, 1 + dataLength);
            m_stream.BeginRead(m_inputData, 1, dataLength, ReadDataCompleted, null);
        }
private void ReadDataCompleted(IAsyncResult ar) { // Get number of bytes read from client Int32 numBytesReadThisTime = m_stream.EndRead(ar); // If client closed connection; abandon this client request if (numBytesReadThisTime == 0) { m_client.Close(); return; } // Continue to read bytes from client until all bytes are in m_bytesReadSoFar += (Byte)numBytesReadThisTime; if (m_bytesReadSoFar private void WriteDataCompleted(IAsyncResult ar) { // After result is written to client, close the connection m_stream.EndWrite(ar); m_client.Close(); } } }

答案 2 :(得分:-1)

首先:停止使用非阻塞套接字。在.NET中,您应该坚持使用同步方法Receive / Send或异步方法BeginReceive / BeginSend

如果你只有少数客户,你应该坚持使用同步方法。然后在新线程中启动每个新客户端。这是最容易使用的选项。

简单地这样做:

public void AcceptClients()
{
     TcpListener listener = new TcpListener(IPAddress.Any, 5566);
     listener.Start();

     while (_serverRunning)
     {
          var socket = listener.AcceptSocket();
          new Thread(ClientFunc).Start(socket);
     }
}

public void ClientFun(object state)
{
    var clientSocket = (Socket)state;
    var buffer = new byte[65535];
    while (_serverRunning)
    {
        //blocking read.
        clientSocket.Receive(buffer, 0, buffer.Length, SocketFlags.None);

        //check packet.

        // handle packet

        // send respons.
        clientSocket.Send(alalalal);
    }
}

您应该重构这些方法,以便它们遵循SRP。该代码只是一个小指南,可以帮助您前进。