如果套接字有问题,我在客户端丢失了数据包,我在服务器中有某种方法可以有效地向许多客户端快速发送3个数据包。调试之后,我发现问题不是服务器本身,而是客户端,他无法读取,我敢打赌,它没有足够快地调用WaitForData,因此他真的不知道自己正在接收数据包。我目前有一个解决方案,但这不是最好的解决方案,因为使用await Task.Delay使服务器瘫痪了。关于如何改善RecibirPaquetes方法的计时的任何想法(这实际上是处理数据包并触发前端应用程序的事件)?或关于如何处理此特定问题的其他任何想法?我在这里把有问题的2种方法留在这里
public void WaitForData()
{
try
{
if (wdCallBack == null)
{
wdCallBack = new AsyncCallback(RecibirPaquetes);
}
SocketPacket theSocPkt = new SocketPacket();
theSocPkt.thisSocket = _cliente;
m_result = _cliente.BeginReceive(theSocPkt.dataBuffer,
0, theSocPkt.dataBuffer.Length,
SocketFlags.None,
wdCallBack,
theSocPkt);
}
catch (SocketException ex)
{
//this basically resets the client if the waitfordata fails
System.Diagnostics.Process.Start("mataPrograma.bat");
}
}
private void RecibirPaquetes(IAsyncResult ar)
{
try
{
SocketPacket server = (SocketPacket)ar.AsyncState;
int cant_recibido;
try
{
cant_recibido = server.thisSocket.EndReceive(ar);
Log("cant_recibido OK", LogSeverity.NORMAL);
}
catch (Exception ex)
{
Log($"cant_recibido Fallo: {ex.Message}", LogSeverity.ERROR);
server.thisSocket.Close();
server.thisSocket = null;
if (ConexionCerrada != null)
{
ConexionCerrada();
}
return;
}
if (cant_recibido == 0)
{
Log($"cantidad recibida es nula se cierra conexion", LogSeverity.NORMAL);
server.thisSocket.Close();
server.thisSocket = null;
if (ConexionCerrada != null)
{
ConexionCerrada();
}
return;
}
server.thisSocket.NoDelay = true;
byte[] paqueteRecibido = new byte[cant_recibido];
Array.Copy(server.dataBuffer, paqueteRecibido, cant_recibido);
var paquete = paqueteRecibido.Deserializar();
if (MensajeRecibido != null)
{
MensajeRecibido(paquete as PaqueteServidor);
Log($"RecibirPaquete: Comando = {((PaqueteServidor)paquete).Comando.ToString()} Contenido = {paquete.Datos}", LogSeverity.NORMAL);
}
else
{
Log($"FALLO! RecibirPaquete: Comando = {((PaqueteServidor)paquete).Comando.ToString()} Contenido = {paquete.Datos}", LogSeverity.ERROR);
}
if (PaqueteComando(paquete as PaqueteServidor) != Comando_Servidor.EXPULSAR && (PaqueteComando(paquete as PaqueteServidor) != Comando_Servidor.CAMBIAR_SESION || soyMonitor))
{
WaitForData();
}
}
catch (Exception ex)
{
Log($"RecibirPaquete: {ex.Message}", LogSeverity.ERROR);
if (MensajeError != null)
{
MensajeError(ex);
}
WaitForData();
}
}
编辑:添加服务器发送数据包的方式
public void EnviarPaquete(PaqueteServidor paquete, Socket cliente, ENVIAR_A tipo, List<ClienteConectado> custom = null)
{
try
{
semaphorePaquetes.Wait();
var conectados = this.clientesConectados.ToList(); //probar esto
paqueteId += 1;
paquete.Serial = paqueteId;
switch (tipo)
{
case ENVIAR_A.TODOS:
foreach (var item in conectados)
{
if (item._socket.Connected)
{
item._socket.Send(paquete.Serializar(), 0, paquete.Serializar().Length, SocketFlags.None);
this.cantPaquetesEnviados += 1;
this.bytesEnviados += Convert.ToUInt64(paquete.Serializar().Length);
}
}
break;
case ENVIAR_A.TODOS_MENOS_TARGET:
foreach (var item in conectados.Where(w => w._socket.RemoteEndPoint.ToString() != cliente.RemoteEndPoint.ToString()))
{
if (item._socket.Connected)
{
item._socket.Send(paquete.Serializar(), 0, paquete.Serializar().Length, SocketFlags.None);
this.cantPaquetesEnviados += 1;
this.bytesEnviados += Convert.ToUInt64(paquete.Serializar().Length);
}
}
break;
case ENVIAR_A.SOLO_LEGISLADORES:
foreach (var item in conectados.Where(w => w.Actor.Labor.id_cargo_tipo == 0))
{
if (item._socket.Connected)
{
item._socket.Send(paquete.Serializar(), 0, paquete.Serializar().Length, SocketFlags.None);
this.cantPaquetesEnviados += 1;
this.bytesEnviados += Convert.ToUInt64(paquete.Serializar().Length);
}
}
break;
case ENVIAR_A.ESTRADO:
foreach (var item in conectados.Where(w => w.Estrado == true))
{
if (item._socket.Connected)
{
item._socket.Send(paquete.Serializar(), 0, paquete.Serializar().Length, SocketFlags.None);
this.cantPaquetesEnviados += 1;
this.bytesEnviados += Convert.ToUInt64(paquete.Serializar().Length);
}
}
break;
case ENVIAR_A.NO_ESTRADO:
foreach (var item in conectados.Where(w => w.Estrado == false))
{
if (item._socket.Connected)
{
item._socket.Send(paquete.Serializar(), 0, paquete.Serializar().Length, SocketFlags.None);
this.cantPaquetesEnviados += 1;
this.bytesEnviados += Convert.ToUInt64(paquete.Serializar().Length);
}
}
break;
case ENVIAR_A.TARGET:
if (cliente.Connected)
{
cliente.Send(paquete.Serializar(), 0, paquete.Serializar().Length, SocketFlags.None);
this.cantPaquetesEnviados += 1;
this.bytesEnviados += Convert.ToUInt64(paquete.Serializar().Length);
}
break;
case ENVIAR_A.CUSTOM:
foreach (var item in custom)
{
if (item._socket.Connected)
{
item._socket.Send(paquete.Serializar(), 0, paquete.Serializar().Length, SocketFlags.None);
this.cantPaquetesEnviados += 1;
this.bytesEnviados += Convert.ToUInt64(paquete.Serializar().Length);
}
}
break;
}
}
catch (Exception ex)
{
aLogear.Enqueue(new Log("EnviarPaquete: " + ex.Message, TipoLog.ERROR, ClaseLog.SERVER));
}
finally
{
semaphorePaquetes.Release();
}
}