2014-09-02 7 views
0

Сообщество Hello StackOverFlow, я работаю над программой на C#, которая зависит от многих соединений сокетов для одного и того же сервера.
Я хотел бы сделать многопоточность на моих классах соединений так что я буду иметь возможность создавать столько соединений, как я хочу, не создавая много классов
Однако Кодекс объяснить это Abit:
шлюз (подключение Thread)Многопоточные разъемы C#?

using SilkroadSecurityApi; 
using System; 
using System.Collections.Generic; 
using System.Net.Sockets; 
using System.Threading; 

namespace ConsoleLogin1 
{ 
    public class Gateway 
    { 
     public static MainClass MainWindow; 
     public static ServerEnum Server = ServerEnum.None; 
     public static List<Packet> GatewayPackets = new List<Packet>(); 
     public static TransferBuffer GatewayRecvBuffer = new TransferBuffer(0x1000, 0, 0); 
     public static Security GatewaySecurity = new Security(); 
     public static Socket GatewaySocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
     public static Thread loop; 
     public enum ServerEnum 
     { 
      None, 
      Gateway, 
      Agent 
     } 
     public void Gateway_thread() 
     { 
      while (true) 
      { 
       SocketError success; 
       byte[] bytes; 
       GatewayRecvBuffer.Size = GatewaySocket.Receive(GatewayRecvBuffer.Buffer, 0, GatewayRecvBuffer.Buffer.Length, SocketFlags.None, out success); 
       if (success != SocketError.Success) 
       { 
        if (success != SocketError.WouldBlock) 
        { 
         return; 
        } 
       } 
       else if (GatewayRecvBuffer.Size > 0) 
       { 
        GatewaySecurity.Recv(GatewayRecvBuffer); 
       } 
       else 
       { 
        return; 
       } 
       List<Packet> collection = GatewaySecurity.TransferIncoming(); 
       if (collection != null) 
       { 
        GatewayPackets.AddRange(collection); 
       } 
       if (GatewayPackets.Count > 0) 
       { 
        foreach (Packet packet in GatewayPackets) 
        { 
         //incoming packets 
        } 
        GatewayPackets.Clear(); 
       } 
       List<KeyValuePair<TransferBuffer, Packet>> list2 = GatewaySecurity.TransferOutgoing(); 
       if (list2 != null) 
       { 
        foreach (KeyValuePair<TransferBuffer, Packet> pair in list2) 
        { 
         TransferBuffer key = pair.Key; 
         Packet packet = pair.Value; 
         success = SocketError.Success; 
         while (key.Offset != key.Size) 
         { 
          int num19 = GatewaySocket.Send(key.Buffer, key.Offset, key.Size - key.Offset, SocketFlags.None, out success); 
          if ((success != SocketError.Success) && (success != SocketError.WouldBlock)) 
          { 
           break; 
          } 
          key.Offset += num19; 
          Thread.Sleep(1); 
         } 
         if (success != SocketError.Success) 
         { 
          break; 
         } 
         bytes = packet.GetBytes(); 
        } 
        if (success != SocketError.Success) 
        { 
         return; 
        } 
       } 
       Thread.Sleep(1); 
      } 
     } 
     public static void SendToServer(Packet packet) 
     { 
      GatewaySecurity.Send(packet); 
     } 

     public void Connect(string IP, string Port) 
     { 
      loop = new Thread(new ThreadStart(this.Gateway_thread)); 
      GatewaySocket.Connect(IP, int.Parse(Port)); 
      loop.Start(); 
      GatewaySocket.Blocking = false; 
      GatewaySocket.NoDelay = true; 
     } 
    } 
} 

Main Class

using System; 
using System.Threading.Tasks; 
using SilkroadSecurityApi; 
using System.Threading; 

namespace ConsoleLogin1 
{ 
    public class MainClass 
    { 
     public string ip = "25.122.17.189"; 
     public string port = "15779"; 
     public string locale = "22"; 
     public string version = "190"; 
     static void Main(string[] args) 
     { 
      new MainClass().Start(); 
     } 
     public void Start() 
     { 
      Gateway.MainWindow = this; 
      new Gateway().Connect(ip, port); 
     } 
    } 
} 

Однако я перепробовал много способов, таких как:

Gateway G1 = new Gateway(); 
Gateway G2 = new Gateway(); 

также начинают новые темы

Thread G1 = new Thread(new ThreadStart(Gateway.Connect)) 
Thread G2 = new Thread(new ThreadStart(Gateway.Connect)) 

, но никоим образом, никогда не может создать новый GatewaySocket в то время как есть уже открытые соединения. В любом случае, мой вопрос снова: как я могу многопоточно использовать Gateway, и у каждого из них есть собственное соединение?

Заранее благодарен.

+3

Вы не можете одновременно создавать несколько сокетов для одного и того же порта. Вам нужно, чтобы каждый сокет прослушивал другой порт. – Servy

+0

, если вы начинаете слушать порт. он заблокирован для каждого сокета в .NET. вы можете сделать обходной путь с помощью WinAPI, но это еще одна несказанная история –

+0

@Servy нет лучшего способа и быстрее сделать это? – Muhab

ответ

0

Soo вот как я бы это сделать:

  1. Я бы определил различные классы:

    • Connection
    • Команда
    • ActionController
    • GUI
  2. Класс соединения:

    public class Connection 
    { 
        public string ip = ""; 
        public string port = ""; 
        public bool listening = false; 
    
        public TcpClient tcpClient; 
        private BackgroundWorker bw = new BackgroundWorker(); 
        private NetworkStream stream; 
    
        public delegate DataReceivedEvent(Byte[] data, TcpEventArgs e); 
        public DataReceivedEvent dataReceived; 
    
        public List<Command> commands = new List<Command>(); 
    
        //for Debugging purpose 
        public string lastError = ""; 
    
        public Connection(string ip, string port) 
        { 
         this.ip = ip; 
         this.port = port; 
         bw.WorkerSupportsCancellation = true; 
    
         if(!Connect()) 
         { 
          return; 
          //maybe do something here? 
         }     
        } 
    
        public bool Connect() 
        { 
         try 
         { 
          tcpClient.Connect(ip, port); 
          stream = tcpClient.GetStream(); 
          return true; 
         } 
         catch(Exception ex) 
         { 
          lastError = ex.Message + " - " + ex.StackTrace; 
          return false; 
         } 
        } 
    
        public void BeginListening() 
        { 
         bw.DoWork += listenToNetwork(); 
         bw.RunWorkerAsync(); 
        } 
    
        public void EndListening() 
        { 
         bw.CancelAsync(); 
        } 
    
        private void listenToNetwork(Object sender, DoWorkEventArgs e) 
        { 
         while(!PendingCancellation) 
         { 
          Byte[] bytes = new Byte[preferedLenghth]; 
          listening = true; 
          Int32 bytesRead = stream.Read(bytes, 0, bytes.Length); 
          if(dataReceived != null) 
          { 
           dataReceived(bytes, new TcpEventArgs(bytesRead)); 
          } 
         } 
         listening = false; 
        } 
    
        public void SendCommands() 
        { 
         foreach(Command cmd in commands) 
         { 
          cmd.Execute(ref stream); 
         } 
        } 
    } 
    
  3. Класс Command:

    // i made a seperate class of Command because it is easy to expand without getting monsterclasse 
    public class Command 
    { 
        private CommandEnum cmd; 
    
        public Command(CommandEnum cmd) 
        { 
         this.cmd = cmd; 
        } 
    
        public void Execute(ref NetworkStream stream) 
        { 
         switch(cmd) 
         { 
          //insert commands like stream.write(bytesToSend, 0, bytesToSend.Length); 
          default: 
          break; 
         } 
        } 
    } 
    
  4. Класс ActionController:

    public ActionController 
    { 
        public Connection conn; 
    
        public ActionController(string ip, string port) 
        { 
         conn = new Connection(ip, port) 
         conn.dataReceived += dataReceivedevent; 
        } 
    
        public void dataReceivedevent(Byte[] data, TcpEventArgs e) 
        { 
         //Do something with the received data here 
        } 
        //Do everything here! the Controller is here to provide necessary information for the GUI 
    } 
    

    .5 Графический интерфейс на вашей фантазии;)

Я думаю, что код не требует объяснений, если что-то неясно

+0

Извините, Себастьян, но это даже не подключится к самому игровому серверу из шелковой дороги. как-то silkroad игровой сервер и клиент по-разному созданы для соединений, даже есть порт для ведения журнала и другой порт для воспроизведения. – Muhab

+0

@Bugs Bunny затем использует два соединения с разными портами, вам просто нужно создать два экземпляра Connection –

Смежные вопросы