2015-02-09 79 views
0

我試圖爲每個連接到服務器的人創建一個數組。Winsock中的數組異步

但是,當服務器接收到信息時,連接起作用,我無法知道是誰發送了這些信息。

我如何知道發送信息的「客戶」列表的索引是誰?

看代碼:

基本定義

public string Ip { get; set; } 
public Socket Ansyc { get; set; } 
public int Index { get; set; } 
public int Id { get; set; } 
public UserConnection(Socket t, int i) { Ansyc = t; Id = i; } 

的Winsock

using System; 
using System.Net; 
using System.Net.Sockets; 
using System.Text; 
using System.Threading; 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace ACESERVER 
{ 
    // State object for reading client data asynchronously 
public class StateObject { 
    // Client socket. 
    public Socket workSocket = null; 
    // Size of receive buffer. 
    public const int BufferSize = 1024; 
    // Receive buffer. 
    public byte[] buffer = new byte[BufferSize]; 
    // Received data string. 
    public StringBuilder sb = new StringBuilder(); 
} 
    class WinsockAnsyc 
    { 
    //clients 
    public static List<UserConnection> Clients = new List<UserConnection>(100); 
    // Thread signal. 
    public static ManualResetEvent allDone = new ManualResetEvent(false); 


    public static void StartListening() { 
     // Data buffer for incoming data. 
     byte[] bytes = new Byte[1024]; 

     // Establish the local endpoint for the socket. 
     // The DNS name of the computer 
     // running the listener is "host.contoso.com". 
     IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName()); 
     IPAddress ipAddress = IPAddress.Any; 
     IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 5000); 

     // Create a TCP/IP socket. 
     Socket listener = new Socket(AddressFamily.InterNetwork, 
     SocketType.Stream, ProtocolType.Tcp); 

     // Bind the socket to the local endpoint and listen for incoming connections. 
     try { 
      listener.Bind(localEndPoint); 
      listener.Listen(100); 

      while (true) { 
       // Set the event to nonsignaled state. 
       allDone.Reset(); 

       // Start an asynchronous socket to listen for connections. 
       Console.WriteLine("Aguardando conexão..."); 
       listener.BeginAccept( 
        new AsyncCallback(AcceptCallback), 
        listener); 

       // Wait until a connection is made before continuing. 
       allDone.WaitOne(); 
      } 

     } catch (Exception e) { 
      Console.WriteLine(e.ToString()); 
     } 

     Console.WriteLine("\nPress ENTER to continue..."); 
     Console.Read(); 

    } 

    public static void AcceptCallback(IAsyncResult ar) { 

     // Signal the main thread to continue. 
     allDone.Set(); 

     // Socket \o/. 
     Socket listener = (Socket) ar.AsyncState; 
     Socket handler = listener.EndAccept(ar); 

     //Adicionamos ele na lista 
     Clients.Add(new UserConnection(handler, Clients.Count())); 
     //Vamos analisar qual index está disponível para o jogador 

     for (int i = 0; i < 100; i++)  
     {  
      if (UserConnection.CheckIndex(i)) 
      { 
       WinsockAnsyc.Clients[(Clients.Count() - 1)].Index = i; 
       break; 
      }  
     } 


     //Zerar o Player_HighIndex pra evitar problemas 

     Globals.Player_HighIndex = 0; 


     //Vamos atualizar o Player_HighIndex sem frescura 

     for (int i = 0; i < Clients.Count(); i++) 
     { 
      if (WinsockAnsyc.Clients[i].Index > Globals.Player_HighIndex) 
      { 
       Globals.Player_HighIndex = WinsockAnsyc.Clients[i].Index; 
      } 
     } 

     //Vamos atualizar o Player_HighIndex para todos os jogadores 
     SendData.Send_UpdatePlayerHighIndex(); 

     //WinsockAnsyc.Clients[Clients.Count() - 1].ListIndex = Clients.Count() - 1; 
     Listen.Log(String.Format("Cliente conectado: {0}", Clients.Count() - 1)); 

     // Create the state object. 
     StateObject state = new StateObject(); 
     state.workSocket = Clients[Clients.Count - 1].Ansyc; 
     Clients[Clients.Count - 1].Ansyc.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, 
      new AsyncCallback(ReadCallback), state); 
    } 


    public static void ReadCallback(IAsyncResult ar) { 
     String content = String.Empty; 
     // Retrieve the state object and the handler socket 
     // from the asynchronous state object. 
     StateObject state = (StateObject) ar.AsyncState; 
     Socket handler = state.workSocket; 
     handler. 

     // Clients[Clients.Count - 1].Ansyc.EndReceive(ar) 
     // Read data from the client socket. 
     int bytesRead = handler.EndReceive(ar); 

     if (bytesRead > 0) { 
      // There might be more data, so store the data received so far. 
      state.sb.Append(Encoding.UTF8.GetString(
       state.buffer,0,bytesRead)); 
      // Check for end-of-file tag. If it is not there, read 
      // more data. 
      content = state.sb.ToString(); 
      Server.Network.ReceiveData.SelectPacket(client.Index, content); 
      if (content.IndexOf("<EOF>") > -1) { 
       // All the data has been read from the 
       // client. Display it on the console. 
       Console.WriteLine("Read {0} bytes from socket. \n Data : {1}", 
        content.Length, content); 
       // Echo the data back to the client. 
       Send(handler, content); 
      } else { 
       // Not all data received. Get more. 
       handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, 
       new AsyncCallback(ReadCallback), state); 
      } 
     } 
    } 

    private static void Send(Socket handler, String data) { 
     // Convert the string data to byte data using ASCII encoding. 
     byte[] byteData = Encoding.ASCII.GetBytes(data); 

     // Begin sending the data to the remote device. 
     handler.BeginSend(byteData, 0, byteData.Length, 0, 
      new AsyncCallback(SendCallback), handler); 
    } 

    private static void SendCallback(IAsyncResult ar) { 
     try { 
      // Retrieve the socket from the state object. 
      Socket handler = (Socket) ar.AsyncState; 

      // Complete sending the data to the remote device. 
      int bytesSent = handler.EndSend(ar); 
      Console.WriteLine("Sent {0} bytes to client.", bytesSent); 

      handler.Shutdown(SocketShutdown.Both); 
      handler.Close(); 

     } catch (Exception e) { 
      Console.WriteLine(e.ToString()); 
     } 
    } 
    } 
} 

任何富人提示或解決方案?

回答

0

您的StateObject類應包含識別客戶端所需的所有必要上下文。您通常不需要諮詢客戶列表來處理單個客戶的個人I/O操作,因爲該StateObject應該足夠。

沒有a more complete code example,我不能比這更具體。

+0

我需要知道誰是:WinsockAnsyc.Clients [i] .Index在收到數據時。 – user3571412 2015-02-09 03:10:47

+0

@ user3571412:你不清楚。 「誰是指數」甚至意味着什麼?你是說你需要知道表達式'WinsockAnsyc.Clients [i] .Index'中'i'的值嗎?無論如何,就像我寫的那樣,您的'StateObject'類應該包含處理I/O操作時需要的所有信息。如果它現在沒有這些信息,只需添加它。然後你會擁有它。 – 2015-02-09 03:13:25

+0

我如何添加它? – user3571412 2015-02-09 03:14:36