代码之家  ›  专栏  ›  技术社区  ›  calvin11 Kousha

C#中无环回的异步套接字

  •  0
  • calvin11 Kousha  · 技术社区  · 6 年前

    我应该如何在两台不同的电脑之间异步使用套接字?我的问题出现了,因为到目前为止,应用程序是在环回中运行的,在同一台PC上初始化客户端和服务器。

    但我不知道如何使用我拥有的相同异步方案在两台远程PC之间建立连接。

    public class Escuchar {
      ManualResetEvent todoListo = new ManualResetEvent(false);
      public delegate void Recibido(Serializador r);
      public event Recibido objetoRecibido;
    
      Socket escuchador;
      public void Comenzar(int puerto) {
        escuchador = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        escuchador.Bind(new IPEndPoint(IPAddress.Loopback, puerto));
        Console.WriteLine("\n\nServidor iniciado.");
        EsperarRespuesta();
      }
    
      public void EsperarRespuesta() {
        todoListo.Reset();
        escuchador.Listen(100);
        escuchador.BeginAccept(Aceptar, escuchador);
      }
    
      public void Aceptar(IAsyncResult resultado) {
        Serializador respuesta = new Serializador();
        respuesta.Socket = ((Socket) resultado.AsyncState).EndAccept(resultado);
        respuesta.Socket.BeginReceive(respuesta.buffer, 0, respuesta.buffer.Length, SocketFlags.None, Receive, respuesta);
      }
    
      public void Receive(IAsyncResult resultado) {
        Serializador respuesta = (Serializador) resultado.AsyncState;
        int read = respuesta.Socket.EndReceive(resultado);
        if (read > 0) {
          for (int i = 0; i < read; i++) {
            respuesta.TransmisionBuffer.Add(respuesta.buffer[i]);
          }
          if (read == respuesta.buffer.Length) {
            respuesta.Socket.BeginReceive(respuesta.buffer, 0, respuesta.buffer.Length, SocketFlags.None, Receive, respuesta);
            Console.WriteLine("\n\nNo encaja!");
          } else {
            Listo(respuesta);
          }
        } else {
          Listo(respuesta);
        }
      }
    
      public void Listo(Serializador respuesta) {
        Console.WriteLine("\n\nDeserializando respuesta...");
        Serializador deserializado = respuesta.Deserializar();
        objetoRecibido(deserializado);
        todoListo.Set();
      }
    }
    

    这是我的序列化程序:

    [Serializable]
    public class Serializador {
      [NonSerialized]
      public Socket Socket;
      [NonSerialized]
      public List < byte > TransmisionBuffer = new List < byte > ();
      [NonSerialized]
      public byte[] buffer = new byte[1024];
    
      public ClaseGuardarJuego claseGuardarJuego = new ClaseGuardarJuego();
    
      public byte[] Serializar() {
        SoapFormatter formatter = new SoapFormatter();
        MemoryStream mem = new MemoryStream();
        formatter.Serialize(mem, this);
        return mem.GetBuffer();
      }
    
      public Serializador Deserializar() {
        try {
          byte[] datosBuffer = TransmisionBuffer.ToArray();
          SoapFormatter formatter = new SoapFormatter();
          MemoryStream mem = new MemoryStream();
          mem.Write(datosBuffer, 0, datosBuffer.Length);
          mem.Seek(0, 0);
          return (Serializador) formatter.Deserialize(mem);
        } catch (SerializationException e) {
          Console.WriteLine("\n\nFallo la deserializacion. Razón: " + e.Message);
          return null;
        }
      }
    }
    

    这是我的发件人:

    public class Enviar {
      ManualResetEvent todoListo = new ManualResetEvent(false);
      Serializador respuesta = new Serializador();
      private int puerto;
    
      public void ConfigurarClase(Juego game, Jugador player) {
        respuesta.claseGuardarJuego.SetDatos(game, player);
      }
    
      public void Comenzar(int puerto) {
        this.puerto = puerto;
        Console.WriteLine("\n\nCliente esperando por una conexion...");
        todoListo.Reset();
        Socket emisor = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        emisor.BeginConnect(new IPEndPoint(IPAddress.Loopback, puerto), Conectar, emisor);
        todoListo.WaitOne();
      }
    
      public void Conectar(IAsyncResult resultado) {
        try {
          respuesta.Socket = (Socket) resultado.AsyncState;
          respuesta.Socket.EndConnect(resultado);
          byte[] buffer = respuesta.Serializar();
          respuesta.Socket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, Send, respuesta);
        } catch (SocketException) {
          Console.WriteLine("\n\nServidor caído, reintentando...");
          Thread.Sleep(1000);
          Comenzar(puerto);
        }
      }
    
      public void Send(IAsyncResult result) {
        Serializador respuesta = (Serializador) result.AsyncState;
        int size = respuesta.Socket.EndSend(result);
        Console.WriteLine("Enviando dato: " + respuesta.claseGuardarJuego.Jugador.NombreJugador);
        todoListo.Set();
      }
    }
    

    我知道我必须获得个人电脑的IP地址,然后发送,但我不知道如何应用它。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Klaus Gütter    6 年前

    IPAddress.Loopback 当连接时,所以

    public void Comenzar(IPAdress ipAddress, int puerto) {
        this.puerto = puerto;
        Console.WriteLine("\n\nCliente esperando por una conexion...");
        todoListo.Reset();
        Socket emisor = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        emisor.BeginConnect(new IPEndPoint(ipAddress, puerto), Conectar, emisor);
        todoListo.WaitOne();
      }