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

时间:2018-12-01 03:12:40

标签: c# ip remote-server asyncsocket

如何在两台不同的PC之间异步使用套接字?之所以引起我的问​​题,是因为到目前为止,该应用程序都以环回方式运行,从而在同一台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地址,然后再发送它,但我不知道如何应用它。

1 个答案:

答案 0 :(得分:1)

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