簡體   English   中英

C#套接字服務器-並發連接問題

[英]C# Socket Server - Issue with Concurrent Connections

嘿,我已經用C#為正在開發的Flash游戲制作了一個套接字服務器,我從某個地方獲得了代碼,並且我是c#和.net開發的初學者。 實際上,當建立連接並且服務器正常運行時,它可以正常工作。 同時獲得2個並發連接,我們遇到了問題。

以下是套接字服務器的基本方面:(出於明顯的原因而取出)

我怎樣才能改變它,使其可以處理並發連接? 我應該在每個響應中添加線索嗎?

謝謝

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")); } } 

[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") { } } } } } 

}

您無需使用同步函數,而可以使用諸如Socket.BeginReceive之類的異步函數。

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(); } } }

首先:停止使用非阻塞套接字。 在.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。 該代碼只是幫助您入門的一個小指南。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM