C# 中的异步套接字没有环回

Sockets asynchronous in C# without loopback

我应该如何在两台不同的电脑之间异步使用套接字?出现我的问题是因为到目前为止,应用程序 运行 在环回中初始化同一台 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();
  }
}

我知道我必须获取PC的IP地址然后发送,但我不知道如何应用。

唯一需要更改的是在连接时使用对方的 IP 地址而不是 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();
  }