2014-09-02 128 views
0

你好StackOverFlow社區,我正在一個C#程序,它依賴於同一個服務器的許多套接字連接。
我願做多線程我的連接類的,所以我就可以,因爲我想創造儘可能多的連接,而無需創建多個類
但是代碼會解釋升技:
網關(連接螺紋)多線程套接字連接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; 
     } 
    } 
} 

主類

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雖然已經有一個打開的連接。 無論如何,我的問題再次是:我怎麼可以做多線程的網關,每個人都有自己的連接?

在此先感謝。

+3

您不能同時爲同一個端口創建多個套接字。您需要讓每個套接字監聽不同的端口。 – Servy 2014-09-02 20:09:32

+0

如果你開始收聽一個端口。它在.NET中被鎖定爲每個套接字。你可以用WinAPI做一個解決方法,但那是另一個不可告人的故事 – 2014-09-02 20:14:49

+0

@Servy沒有更好的方法,更快地做到這一點? – Muhab 2014-09-02 20:15:05

回答

0

這裏洙是我應該怎樣做:

  1. 我會定義各種類:

    • 連接
    • 命令
    • 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 GUI是在你的想象;)

我認爲代碼是一種不言自明的問題,如果有些事情不清楚

+0

對不起,塞巴斯蒂安,但這甚至不會連接到silkroad的遊戲服務器本身。以某種方式silkroad遊戲服務器和客戶端是不同的連接,即使有一個端口登錄和另一個端口播放.. – Muhab 2014-09-04 00:08:25

+0

@Bugs Bunny然後使用兩個連接與不同的端口,你只需要創建兩個連接實例 – 2014-09-04 05:40:36