2014-09-02 114 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